0

I have users indexed with categories as follows

{
 id: 1
 name: John
 categories: [
   {
    id: 1
    name: Category 1
   },
   {
    id: 2
    name: Category 2
   }
 ]
},
{
 id: 2
 name: Mark
 categories: [
   {
    id: 1
    name: Category 1
   }
 ]
}

And I'm trying to get all the documents with Category 1 or Category 2 with

{
 filter:
   {
     bool: {
       must: [
         {
           terms: {user.categories.id: [1, 2]}
         }
       ]
     }
   }
}

But It only returns the first document that has the two categories, what I am doing wrong? As I understood, terms search that one of the values is contained in the field, so for user 1 user.categories.id: [1, 2] user 2 user.categories.id: [1] Categoy id 1 is contained in both documents

1 Answer 1

1

The best way to handle this is probably with a nested filter. You'll have to specify the "nested" type in your mapping, though.

I can set up an index like this:

PUT /test_index
{
   "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 0
   },
   "mappings": {
      "doc": {
         "properties": {
            "categories": {
               "type": "nested",
               "properties": {
                  "id": {
                     "type": "long"
                  },
                  "name": {
                     "type": "string"
                  }
               }
            },
            "id": {
               "type": "long"
            },
            "name": {
               "type": "string"
            }
         }
      }
   }
}

then add some docs:

PUT /test_index/doc/1
{
   "id": 1,
   "name": "John",
   "categories": [
      { "id": 1, "name": "Category 1" },
      { "id": 2, "name": "Category 2" }
   ]
}

PUT /test_index/doc/2
{
   "id": 2,
   "name": "Mark",
   "categories": [
      { "id": 1, "name": "Category 1" }
   ]
}

PUT /test_index/doc/3
{
   "id": 3,
   "name": "Bill",
   "categories": [
      { "id": 3, "name": "Category 3" },
      { "id": 4, "name": "Category 4" }
   ]
}

Now I can use a nested terms filter like this:

POST /test_index/doc/_search
{
   "query": {
      "constant_score": {
         "filter": {
         "nested": {
            "path": "categories",
            "filter": {
                "terms": {
                   "categories.id": [1, 2]
                }
            }
         }
         },
         "boost": 1.2
      }
   }
}
...
{
   "took": 3,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 2,
      "max_score": 1,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "1",
            "_score": 1,
            "_source": {
               "id": 1,
               "name": "John",
               "categories": [
                  {
                     "id": 1,
                     "name": "Category 1"
                  },
                  {
                     "id": 2,
                     "name": "Category 2"
                  }
               ]
            }
         },
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "2",
            "_score": 1,
            "_source": {
               "id": 2,
               "name": "Mark",
               "categories": [
                  {
                     "id": 1,
                     "name": "Category 1"
                  }
               ]
            }
         }
      ]
   }
}

Here is the code I used:

http://sense.qbox.io/gist/668aefe910643b52a3a10d40aca67104491668fc

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.