# List of string must match all provided values

**URL:** <https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351>\
**Category:** Elasticsearch\
**Created:** [July 8, 2020, 1:12pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351 "2020-07-08T13:12:09Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nicolas\_Rey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nicolas_rey/32/47284_2.png) [@Nicolas\_Rey](https://discuss.elastic.co/u/Nicolas_Rey)\
**Post date:** [July 8, 2020, 1:12pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/1 "2020-07-08T13:12:09Z")

</div>

Hi,

I'm new to Elastic Search, and I simply would like to make a query that filter all entries that have exactly all the supplied values (not an OR **but an AND** ).

Here is an example of my document

```auto
[
    {
    "Areas" : [
    "Area A",
    "Area B",
    "Area C",
    "Area D"
    ],
    "UserId" : "User 1"
    },
    {
    "Areas" : [
    "Area A",
    "Area C",
    ],
    "UserId" : "User 2"
    }
]

```

Let's say I want to filter all entries where Areas contains all the values "Area A" **and**"Area B"

I tried with the **terms** filter but it provides an OR filering, so here both my User 1 and User 2 are selected where I would like only the User 1

```auto
      "query": {
        "bool": {
          "must": [
            {
              "terms": {
                "areas.keyword": [
                  "Area A",
                  "Area B"
                ]
              }
            }
          ]
    	 }
    	}

```

Here is the field mapping

```auto
        "areas": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }

```

Could you help me please ?  
Thank you

---

<div class="post-metadata">

**Author:** ![Nicolas\_Rey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nicolas_rey/32/47284_2.png) [@Nicolas\_Rey](https://discuss.elastic.co/u/Nicolas_Rey)\
**Post date:** [July 8, 2020, 1:38pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/2 "2020-07-08T13:38:14Z")

</div>

I tried this

```auto
  "query": {
    "bool": {
      "must": [
		{
          "match_phrase": {
            "areas": "Area A"
          }
        },
          {
          "match_phrase": {
            "areas": "Area B"
          }
        }
      ]
	 }
	}

```

it seems to work, but is it correct or does it exist a better solution ?

---

<div class="post-metadata">

**Author:** ![Vinayak\_Sapre](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/vinayak_sapre/32/45939_2.png) [@Vinayak\_Sapre](https://discuss.elastic.co/u/Vinayak_Sapre)\
**Post date:** [July 8, 2020, 6:51pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/3 "2020-07-08T18:51:40Z")

</div>

@Nicolas_Rey  
Can you try this

```auto
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "Areas.keyword": "Area A"
          }
        },
        {
          "term": {
            "Areas.keyword": "Area B"
          }
        }
      ]
    }
  },
  "sort": [
    {
      "_doc": {
        "order": "asc"
      }
    }
  ]
}

```

Also note your mapping has field name areas lower case A. But document has field with upper case A.

---

<div class="post-metadata">

**Author:** ![Christian\_Dahlqvist](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/christian_dahlqvist/32/4617_2.png) [@Christian\_Dahlqvist](https://discuss.elastic.co/u/Christian_Dahlqvist)\
**Post date:** [July 8, 2020, 7:00pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/4 "2020-07-08T19:00:30Z")

</div>

Have you looked at the [terms set query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-set-query.html)?

---

<div class="post-metadata">

**Author:** ![Nicolas\_Rey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nicolas_rey/32/47284_2.png) [@Nicolas\_Rey](https://discuss.elastic.co/u/Nicolas_Rey)\
**Post date:** [July 9, 2020, 6:56am UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/5 "2020-07-09T06:56:11Z")

</div>

@Vinayak_Sapre

Hi, thanks it seems to work correctly, is there any difference using your solution (term) vs mine (match\_phrase) ?

---

<div class="post-metadata">

**Author:** ![Nicolas\_Rey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nicolas_rey/32/47284_2.png) [@Nicolas\_Rey](https://discuss.elastic.co/u/Nicolas_Rey)\
**Post date:** [July 9, 2020, 6:59am UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/6 "2020-07-09T06:59:22Z")

</div>

@Vinayak_Sapre

comparing the score  
match\_phrase : max\_score" : 4.4969654  
term: "max\_score" : 8.961212

I don't know if it's significant ?

---

<div class="post-metadata">

**Author:** ![Vinayak\_Sapre](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/vinayak_sapre/32/45939_2.png) [@Vinayak\_Sapre](https://discuss.elastic.co/u/Vinayak_Sapre)\
**Post date:** [July 9, 2020, 7:26am UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/7 "2020-07-09T07:26:13Z")

</div>

@Nicolas_Rey

> [@Nicolas\_Rey](#):
>
> Hi, thanks it seems to work correctly, is there any difference using your solution (term) vs mine (match\_phrase) ?

Phrase query is typically used if you want to match token "Area" followed by token "A" anywhere in a long analyzed string. So "Foo Area A Bar" will match too.

I think your requirement is "exact match" which is achieved by Term query. For exact match there is no need to compute score. So you sort on some field (\_doc if no specific sorting required) or wrap it in a constant score query to avoid scoring overhead.

Best if you can profile queries using by adding "profile": true to see how breakdown looks.

---

<div class="post-metadata">

**Author:** ![Nicolas\_Rey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nicolas_rey/32/47284_2.png) [@Nicolas\_Rey](https://discuss.elastic.co/u/Nicolas_Rey)\
**Post date:** [July 9, 2020, 8:54am UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/8 "2020-07-09T08:54:14Z")

</div>

@Vinayak_Sapre

Thank I understand now the difference between **term** and **match\_phrase** query.

But when you say :

> For exact match there is no need to compute score. So you sort on some field (\_doc if no specific sorting required) or wrap it in a constant score query to avoid scoring overhead.

I don't understand what you mean here ? Indeed the "max\_score" is a part of the output when I play the DSL query with Kibana. Is it not relevant at all in my case ?

---

<div class="post-metadata">

**Author:** ![Vinayak\_Sapre](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/vinayak_sapre/32/45939_2.png) [@Vinayak\_Sapre](https://discuss.elastic.co/u/Vinayak_Sapre)\
**Post date:** [July 9, 2020, 12:37pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/9 "2020-07-09T12:37:58Z")

</div>

@Nicolas_Rey  
score is required if you want ElasticSearch to determine how well each document matches. ElasticSearch will sort documents based on score so most relevant documents show up at the top. Score is important if you care about

1. Matching part of your query for ex. document field has Area but not A.
2. What's in the field other than what you are searched for. "Foo Area A bar"  
There are other scenarios too.

If you use your match\_phrase query and search for "Area A" , "Area C", the user 2 document will show up on the top because it matches better compared to the user 1 document.

You can experiment running both queries on your data, use "explain": true to understand why one document is preferred over other.

Not sure why after adding sort, Kibana is showing score. It should be null or in case constant query it should be 1 for all matches.

---

<div class="post-metadata">

**Author:** ![Nicolas\_Rey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nicolas_rey/32/47284_2.png) [@Nicolas\_Rey](https://discuss.elastic.co/u/Nicolas_Rey)\
**Post date:** [July 10, 2020, 1:46pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/10 "2020-07-10T13:46:57Z")

</div>

@Vinayak_Sapre

Very clear, thank you!

---

<div class="post-metadata">

**Author:** ![Vinayak\_Sapre](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/vinayak_sapre/32/45939_2.png) [@Vinayak\_Sapre](https://discuss.elastic.co/u/Vinayak_Sapre)\
**Post date:** [July 11, 2020, 4:59am UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/11 "2020-07-11T04:59:06Z")

</div>

@Nicolas_Rey  
Sorry I was wrong about sort. If you do not want to compute score, you need put term queries in filter clause

```auto
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "Areas.keyword": "Area A"
          }
        },
        {
          "term": {
            "Areas.keyword": "Area B"
          }
        }
      ]
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![Nicolas\_Rey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nicolas_rey/32/47284_2.png) [@Nicolas\_Rey](https://discuss.elastic.co/u/Nicolas_Rey)\
**Post date:** [July 13, 2020, 3:39pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/12 "2020-07-13T15:39:32Z")

</div>

@Vinayak_Sapre

If I do such (put term queries in filter clause instead of must clause), will I have the exact same outputs (ie same documents that will be filtered) ?

What is the benefit of not compute the score ?

---

<div class="post-metadata">

**Author:** ![Vinayak\_Sapre](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/vinayak_sapre/32/45939_2.png) [@Vinayak\_Sapre](https://discuss.elastic.co/u/Vinayak_Sapre)\
**Post date:** [July 15, 2020, 6:22am UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/13 "2020-07-15T06:22:41Z")

</div>

@Nicolas_Rey  
Yes you will get same results.

If you don't need score why waste cpu cycles in computing it? For a single query is not going to save you a lot. But If this query is called lots of time time, it adds up.

---

<div class="post-metadata">

**Author:** ![Nicolas\_Rey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nicolas_rey/32/47284_2.png) [@Nicolas\_Rey](https://discuss.elastic.co/u/Nicolas_Rey)\
**Post date:** [July 15, 2020, 1:07pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/14 "2020-07-15T13:07:30Z")

</div>

@Vinayak_Sapre

It makes sense, thank you again

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [August 12, 2020, 1:07pm UTC](https://discuss.elastic.co/t/list-of-string-must-match-all-provided-values/240351/15 "2020-08-12T13:07:31Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
