20

I have a problem with querying objects in array. Let's create very simple index, add a type with one field and add one document with array of objects (I use sense console):

PUT /test/
PUT /test/test/_mapping
{
    "test": {
        "properties": {
            "parent": {"type": "object"}
        }
    }
}
POST /test/test
{
    "parent": [
        {
            "name": "turkey",
            "label": "Turkey"
        },
        {
            "name": "turkey,mugla-province",
            "label": "Mugla (province)"
        }
    ]
}

Now I want to search by both names "turkey" and "turkey,mugla-province" . The first query works fine:

GET /test/test/_search {"query":{ "term": {"parent.name": "turkey"}}}

But the second one returns nothing:

GET /test/test/_search {"query":{ "term": {"parent.name": "turkey,mugla-province"}}}

I tried a lot of stuff including:

"parent": {
    "type": "nested",
    "include_in_parent": true,
    "properties": {
         "label": {
             "type": "string",
             "index": "not_analyzed"
         },
         "name": {
             "type": "string",
             "store": true
         }
     }
}

But nothing helps. What do I miss?

Kaspar Lee
  • 5,446
  • 4
  • 31
  • 54
Nikita
  • 4,435
  • 3
  • 24
  • 44

2 Answers2

25

Here's one way you can do it, using nested docs:

I defined an index like this:

PUT /test_index
{
   "mappings": {
      "doc": {
         "properties": {
            "parent": {
               "type": "nested",
               "properties": {
                  "label": {
                     "type": "string"
                  },
                  "name": {
                     "type": "string"
                  }
               }
            }
         }
      }
   }
}

Indexed your document:

PUT /test_index/doc/1
{
   "parent": [
      {
         "name": "turkey",
         "label": "Turkey"
      },
      {
         "name": "turkey,mugla-province",
         "label": "Mugla (province)"
      }
   ]
}

Then either of these queries will return it:

POST /test_index/_search
{
    "query": {
        "nested": {
           "path": "parent",
           "query": {
               "match": {
                  "parent.name": "turkey"
               }
           }
        }
    }
}

POST /test_index/_search
{
    "query": {
        "nested": {
           "path": "parent",
           "query": {
               "match": {
                  "parent.name": "turkey,mugla-province"
               }
           }
        }
    }
}

Here's the code I used:

http://sense.qbox.io/gist/6258f8c9ee64878a1835b3e9ea2b54e5cf6b1d9e

Sloan Ahrens
  • 8,588
  • 2
  • 29
  • 31
  • Thx for replay but I need an exact match. Sorry that didn't specified it. – Nikita Jun 25 '15 at 23:30
  • 1
    What do you mean by "exact match"? This technique works fine with `terms` queries/filters too, you just might need `"index": "not_analzyed"` on on the mapping field. I can update to show that if it will help. – Sloan Ahrens Jun 25 '15 at 23:32
  • `"index": "not_analzyed"` - that's what i need! I already pointed other answer as correct, but your suites me better. I will use this solution, thank you for your time! – Nikita Jun 25 '15 at 23:43
8

For search multiple terms use the Terms query instead of Term query.

"terms" : {
        "tags" : [ "turkey", "mugla-province" ],
        "minimum_should_match" : 1
    }

There are various ways to construct this query, but this is the simplest and most elegant in the current version of ElasticSearch (1.6)

Alexander Volkov
  • 7,904
  • 1
  • 47
  • 44
  • 1
    `GET /test/test/_search { "query":{ "terms" : { "parent.name" : ["turkey", "turkey,mugla-province" ] } } }` - this one works pretty well! Thx, and I wonder can I somehow point the only one term "turkey,mugla-province" without "turkey"? – Nikita Jun 25 '15 at 23:26
  • 1
    You can by simply stating the minimum_should_match : 2, which will only match docs with both. Also you may want to check your analyzer is not breaking on the , or - which is possible and then retry your Term query, or you can use nested docs with different analyzers, there are lots of way to accomplish specific things with ElasticSearch but I'm afraid I don't understand exactly what you are looking for. – Daniel Hoffmann-Mitscherling Jun 25 '15 at 23:42
  • "[terms] query does not support [minimum_should_match]", in [v7.5 terms](https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-terms-query.html) the key of each term is the property you want to search for, e.g.: `"terms":{"parent.name":[ "turkey", "mugla-province" ]}` – CPHPython Nov 26 '19 at 10:28