Must match multiple fields in nested objects

Hi! I have been trying to implement my application with tagging feature. Tags would consist of name field and value field and be nested objects under value tags.

Code: (taken from response of match_all search)
{ "_source" : { "examinfo": "lots of infos", "tags" : [ { "name" : "subject", "value" : "maths" }, { "name" : "professor", "value" : "Math Master" }, { "name" : "year", "value" : "2016" }, { "name" : "term", "value" : "second" }, { "name" : "grade", "value" : "second" } ], "data" : "exam data - images" } },

So, what I am trying to do is to be able to filter my query with multiple tags and because as you have probably noticed in this example, and yes this will happen :smile:, two different tag-types have the same value. So natural instinct would be to filter them with both 'name'(type) field and value field. (Hope this is the right approach?)

{ "size": 10, "query": { "nested": { "path": "tags", "query": { "bool": { "must": [ { "match": { "tags.year": "2015"}}, { "match": { "tags.term": "second"}}, ] } } } } }

I tried this because I have found an example on stack, which "works" like this. Link: Stack Example

I think this example is very similar to mine as it uses features as I use tags. Sadly, when I tried to implement it in my case, it didn't work. Is there any obvious solution, which I am missing?

So, what I want to do is; I want to be able to search through my database with declaring tags that test must match (user would have selected them). One other question, is it possible to aggregate whole object? In this example, it would be whole tag object?

Also my mappings of data:
{ "template": "*", "order": 0, "settings": { "number_of_shards": 3, "number_of_replicas": 0 }, "mappings": { "exams": { "_timestamp": { "enabled": true }, "properties": { "description": { "type": "string"}, "provider": { "type": "object", "properties": { "name": { "type": "string"}, "uid": { "type": "integer"} } }, "tags": { "type": "nested", "properties": { "name": { "type": "string", "analyzer": "whitespace" }, "value": { "type": "string", "analyzer": "whitespace" } } }, "data": { "type": "nested", "properties": { "preview": { "type": "boolean"}, "order": { "type": "integer"}, "image": { "type": "string"} } } } } } }

Please do try to format your code when posting. It really makes it easier to spot issues!

From what I can tell, the query you provided should not return the document sample you posted. Did you mean to search for the year 2016?

Yes, I meant 2015, but it still doesn't return any successful searches... Is it possible that it is because there actually is no tags.year field and only tags.name:year? Or is there any documentation for this kind of matching?

You're close.

Look at your mapping. You have a nested "tags" object mapped, with properties "name" and "value".

Look at your document. You have a property "tags" whose value is an array of objects, and each of the objects have a "name" property and a "value" property.

Your query needs to reflect that. "tags.name": "year" and "tags.value": "2016".

Note that searching "tags.name": "year" and "tags.value": "second" will not succeed. That is precisely the purpose of the nested mapping and query.

The query form that you are going to need will be a non-nested bool query, with two "must"s, each one itself a nested query - one with bool must "tags.name": "year" and "tags.value": "2016", and the other with bool must "tags.name": "term" and "tags.value": "second"

2 Likes

Thank you so much! Really helpful, I have managed to do it :smile: !