6

I'm trying to create a query/filter that matches a document only if a number of conditions are met on the same item of an array.

Let's say this is the document:

{
  arr: [
    { "f1" : "a" , f2 : true },
    { "f1" : "b" , f2 : false}
  ]
}

I want to be able to retrieve documents that have N conditions matching on the same element. For example: arr.f1 == "a" AND arr.f2 == true should match the document but arr.f1 == "b" AND arr.f2 == true should not.

I'm trying nested bool filters (I have other filters apart from this one) but it doesn't work, something in the lines of

"bool" : {
    "must": [
        { some other filter },
        {"bool": {"must" : [
            {"term" : {"arr.f1" : "a"}},
            {"term" : {"arr.f2" : true}},
        ] }}
    ]
}

Any idea how to do that? thanks

edit: I changed the mapping and now a nested query works as per Val's response. I'm now not able to do an "exists" filter on the nested field:

A simple { "filter" : {"exists" : { "field" : "arr" } } } search returns no hits. How do I do that?

edit: It looks like I need to do a nested exists filter to check that a field inside the nested object exists. something like:

"filter" : {
       "nested" : {"path" : "arr", "filter" : {"exists" : { "field" : "f1" } }}
}

edit: argh - now highlight doesn't work anymore:

   "highlight" : {
        "fields" : [
            {"arr.f1" : {}},
        ]
    }

Worked around that by adding include_in_parent : true and querying both the nested field and the root object. It's just awful. If anyone has a better idea, they're more than welcome!

{   
    "query" : {
        "bool" : {
            "must": [
                {"term" : { "arr.f1" : "a" }},
                { "nested" : { "path" : "arr", 
                   "query" :  { "bool" : { "must" : [ 
                        {"term" : { "arr.f1" : "a" }},
                        {"term" : { "arr.f2" : true }}
                   ] } } 
                }}
            ]
        }
    },
    "highlight" : {
        "fields" : [
            {"arr.f1" : {}},
        ]
    }
}

In case you're wondering: it's legacy stuff. I can't reindex right now (that would be the obvious solution) and I need a quick & dirty workaround

1 Answer 1

6

You need to set the type of your arr field as nested like this:

{
    "your_type": {
        "properties": {
            "arr": {
                "type": "nested",
                "properties": {
                    "f1": {"type":"string"},
                    "f2": {"type":"boolean"}
                }
            }
        }
    }
}

Then you need to use a nested query:

{
    "nested" : {
        "path" : "arr",
        "query" : {
            "bool" : {
                "must" : [
                    {
                        "term" : {"arr.f1" : "a"}
                    },
                    {
                        "term" : {"arr.f2" : true}
                    }
                ]
            }
        }
    }
}

Your exists filter needs to specify the full field path

"filter" : {
       "nested" : {"path" : "arr", "filter" : {"exists" : { "field" : "arr.f1" } }}
}
Sign up to request clarification or add additional context in comments.

5 Comments

nice. How do I do an "exists" filter on a nested array? It doesn't seem to work anymore. Just filtering "exists" : { "field" : "arr" } now returns no docs.
done. Just a simple exists filter on "arr" returns nothing even though all the docs have it.
Ok the "final" version of the query is as bad as it can get. I need both highlighting (because I need to know which of the nested objects matched) and nested filtering. before anyone asks: it's legacy stuff. I can't reindex right now and I need a quick & dirty workaround.
Well, if you cannot reindex, does it mean you could not change the mapping in the first place? that's probably why the exists filter and the highlighting doesn't work anymore.
you're right. I was actually looking for the best solution to be able to choose what to do with the legacy db. I found out highlighting doesn't work with nested queries, it's a known "bug" (or missing feature, I don't know).

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.