Filter range on array of object

I have a documents with many nested fields and array of objects inside them. So when I perform search, how can I get the age range between 20 to 35?

{
    "company_name": "abc company",
    "detail": {
        "staff": [
            {
                "name": "tom",
                "gender": "male",
                "age": 25
            },
            {
                "name": "peter",
                "gender": "male",
                "age": 30
            },
            {
                "name": "mary",
                "gender": "female",
                "age": 22
            },
            {
                "name": "may",
                "gender": "female",
                "age": 18
            },
            {
                "name": "joe",
                "gender": "male",
                "age": 65
            },
            {
                "name": "ken",
                "gender": "male",
                "age": 33
            },
            {
                "name": "ada",
                "gender": "female",
                "age": 17
            },
            {
                "name": "june",
                "gender": "female",
                "age": 55
            }
        ]
    }
}

Also, Is there a way to get the age range between 40 to 70 and male only?

Hi Jake. I assume you have a nested field mapping in your index for this structure? It looks like a nested query is what you are looking for. An example is included in the docs:

hi carly, I checked my mappings seems no nested field.

{
    "staff": {
        "properties": {
            "age": {
                "type": "double"
            },
            "name": {
                "type": "keyword"
            },
            "gender": {
                "type": "keyword"
            }
        }
    }
}

If no nested field, should i create a new one??

Thanks for clarifying. No, if you're not using nested fields I wouldn't add to that as nested searches are computationally more intensive so there may be a performance impact.

Have you considered using a range query on your age attribute for the first query:

These can also be combined in a bool query with other matches as per your second question:

Hope that helps!

For my case, do you means my query should like this:

{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "detail. staff. gender" : "male" }
      },
      "filter" : {
        "range" : {
          "detail.staff.age" : { "gte" : 40, "lte" : 70 }
        }
      },
      "boost" : 1.0
    }
  }
}

There's probably a few ways to do it, but yes that looks to be one possible way.

Boost is normally applied to a particular clause in the query, rather than the entire bool query itself. This blog does cover boosting if that helps.

I tried the query but not working, it still return the staff who is out of age range.

I am using ES 6.3

Elasticsearch will always return the full document that matched. You can as far as I know not get poarts of a document. If you want only the parts that match it might be better to store each staff member as a separate document.

2 Likes

I think that something like inner hits would work in that case but I'd recommend following @Christian_Dahlqvist advice.

1 Like

I'll defer to @Christian_Dahlqvist and @dadoonet in their recommendations. One warning is that 6.3 is EOL, so it might be worth upgrading at least to 6.8. Details of EOL and maintenance support is here.

1 Like

I think @Christian_Dahlqvist advice is the best way.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.