16

I have a set of documents (type 'article') and I want to search for the document that have elements/objects into an array field

{
    "_type": "article",
    "_source": {
        "title": "Article 1",
        "locations": [
            {
                "address": "ES headquarter",
                "city": "Berlin"
            }
        ]
    }
}

I want two queries (just one, but with a little variation):

  • get all the articles that have locations
  • get all the articles that have NO locations

I tried different things but probably I'm too bad with ElasticSearch:

{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": [
        {
          "type": {
            "value": "article"
          }
        },
        {
          "bool": {
            "must_not": {
              "missing": {
                "field": "location",
                "existence": true,
                "null_value": true
              }
            }
          }
        }
      ]
    }
  }
}

this doesn't work.

  • How would you fix my query?

but mainly:

  • How would you perform this search for documents with a field that is an empty array?

3 Answers 3

16

If address is a mandatory field in location array you can modify your query:

"must_not": {
  "missing": {
    "field": "locations.address"
  }
}

AFAIK, in ES you cannot query non-leaf elements (like your location field) (see issue), and in case object types ES flattens the nested fields (see nested type, object type). That's why I suggested to query for one of the leaf elements instead. But it requires that one of them is mandatory (which is unfortunately not satisfied in your case).

Anyway I found the solution using the _source parameter inside the source_filtering:

"must_not": {
  "script": {
    "script": "_source.locations.size() > 0"
  }
}

Note that using "lang":"groovy" you should write: "script": "_source.locations.size > 0"

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

7 Comments

No, it is not a mandatory field; how else could I solve?. And what would be the difference if it was mandatory?.
Wow thanks! This seems to be almost the solution I need :) The problems:_________1) I get a script_lang not supported [groovy] (solved just removing the lang statement); and 2) I get a Error: could not access: size; in class: java.util.ArrayList and I don't know how to proceed with that :(
Ok, it might be beyond my actual knowledge of ES, but here is my tips:
Solved! It was _source.locations.size() > 0! Missed the brackets! It works perfectly now :D! If you update your answer I'll set it as best one ^^
Super! Now it's clear: With mvel script language we should use size(), but with groovy we should use size.
|
15

If you don't want to enable scripting, you can combine the Exists Query with a must_not bool query, e.g:

{
  "query":{
    "bool":{
      "must_not":[
        {
          "exists":{
            "field":"tags"
          }
        }
      ]
    }
  }
}

Comments

6

As per the ElasticSearch documentation

An empty array is treated as a missing field — a field with no values.

Let's suppose you have two documents in the article-index index

# First document
{
    "_type": "article",
    "_source": {
        "title": "Article 1",
        "locations": [{"address": "ES headquarter", "city": "Berlin"}]
    }
}

# Second document
{
    "_type": "article",
    "_source": {
        "title": "Article 2",
        "locations": []
    }
}

Expected queries would be:

  1. Get all the articles that have locations
GET article-index/_search
{
  "query": {
    "exists": {
       "field": "locations"
    }
  }
}
  1. get all the articles that have NO locations
GET article-index/_search
{
  "query": { 
    "bool": {
      "must_not": {
        "exists": {
          "field": "locations"
        }
      }
    }
  }
}

1 Comment

I think you mean must_not on the last example?

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.