0

Part of my mapping is:

"individual_attributes" : {
    "type" : "nested",
        "properties" : {
            "template_id" : {"type" : "integer"},
            "attributes_set" : {
                "type" : "nested",
                "properties" : {
                    "attribute_id" : {"type" : "integer"},
                    "attribute_value" : {"type" : "string", "index" : "not_analyzed"}
                }
            }
        }
    }

I need to filter those document which has attribute_id='x' with attribute_value for given id equals 'y'. So that I need matching for pair of fields. Is it possible? Or do I need to change my mapping to something like this:

"individual_attributes" : {
    "type" : "nested",
        "properties" : {
            "template_id" : {"type" : "integer"},
            "attributes_set" : {
                "type" : "nested",
                "properties" : {
                    "attribute_id" : {"type" : "integer",
                        "properties" : {
                            "attribute_value" : {"type" : "string", "index" : "not_analyzed"}
                        }
                    },

                }
            }
        }
    }

Sample data:

                  "attributes_set": [
                 {
                    "attribute_id": 17,
                    "attribute_value": "dolorum"
                 },
                 {
                    "attribute_id": 15,
                    "attribute_value": "at"
                 },
                 {
                    "attribute_id": 18,
                    "attribute_value": "maxime"
                 },
                 {
                    "attribute_id": 14,
                    "attribute_value": "et"
                 },
                 {
                    "attribute_id": 11,
                    "attribute_value": "nemo"
                 },
                 {
                    "attribute_id": 12,
                    "attribute_value": "rem"
                 },
                 {
                    "attribute_id": 10,
                    "attribute_value": "eius"
                 },
                 {
                    "attribute_id": 19,
                    "attribute_value": "deleniti"
                 },
                 {
                    "attribute_id": 13,
                    "attribute_value": "modi"
                 },
                 {
                    "attribute_id": 16,
                    "attribute_value": "neque"
                 }
              ]

I need: SELECT * WHERE attribute(16, for instance)=value(neque). Another words I need matching of pair of fields within one data set:

{
    "attribute_id": x,
    "attribute_value": "y"
}

2 Answers 2

2

Here is a simplified example. Your first mapping should be fine for what you want to do. I took out one level of nesting to simplify the explanation, but the same principle will work with arbitrary levels of nesting (if you don't see how to generalize my example I can edit the answer with another example).

I set up a simple mapping like this:

PUT /test_index
{
   "mappings": {
      "doc": {
         "properties": {
            "attributes_set": {
               "type": "nested",
               "properties": {
                  "attribute_id": {
                     "type": "integer"
                  },
                  "attribute_value": {
                     "type": "string",
                     "index": "not_analyzed"
                  }
               }
            }
         }
      }
   }
}

Then added two documents with two nested documents each:

POST /test_index/doc/_bulk
{"index":{"_id":1}}
{"attributes_set": [{"attribute_id": 18,"attribute_value": "dolorum"},{"attribute_id": 15,"attribute_value": "at"}]}
{"index":{"_id":2}}
{"attributes_set": [{"attribute_id": 18,"attribute_value": "maxime"},{"attribute_id": 14,"attribute_value": "et"}]}

Now I can query for a document with a specific nested doc as follows:

POST /test_index/_search
{
   "filter": {
      "nested": {
         "path": "attributes_set",
         "filter": {
            "bool": {
               "must": [
                  {
                     "term": {
                        "attributes_set.attribute_id": {
                           "value": 18
                        }
                     }
                  },
                  {
                     "term": {
                        "attributes_set.attribute_value": {
                           "value": "maxime"
                        }
                     }
                  }
               ]
            }
         }
      }
   }
}

which returns:

{
   "took": 24,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "2",
            "_score": 1,
            "_source": {
               "attributes_set": [
                  {
                     "attribute_id": 18,
                     "attribute_value": "maxime"
                  },
                  {
                     "attribute_id": 14,
                     "attribute_value": "et"
                  }
               ]
            }
         }
      ]
   }
}

Here's all the code I used to test it:

http://sense.qbox.io/gist/5e75461a4f0cf96e012cbf0f8262b22f3f8e5ec0

Does that help?

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

4 Comments

Thank you VERY much for your time and patience while you have been writing the answer. Very straight and detailed. That's exactly what I need. I've changed your code for using more nesting levels. Becides, I didn't know about sense.qbox.io. Useful instrument. Thank you for pointing it out too. Now it is time to add aggregations to my filter. )
And how to add more attribute sets? Tried like that, but it didn't work: "bool": [ {"must": [{"term": {...}}, ...]}, {"must": [{"term": {...}}, ...]} ]
You have to take the whole nested clause, and put it inside a bool-must, together with another nested clause that would match the second nested document you are looking for. Remember that the nested filter says, "find a nested document that meets these criteria". If you're looking for more than one nested document, you need more than one nested filter.
Yes, now it works too. Elasticsearch may have rather big and complex queries... And I start to understand how it works. Thank you.
1

It looks like you have the perfect mapping in place for this and so all you need to do is build the right query involving a nested query.

Please refer to Elasticsearch docs on how you can query nested objects. See their Querying a Nested Object doc which I think provides all the details you need and a relevant comments example that resembles your case.

EDIT:

Sorry, I just noticed your question regarding the mapping - your first mapping is correct.

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.