Home > database >  in elastic search, how can get document max value for nested field?
in elastic search, how can get document max value for nested field?

Time:02-14

is My Mapping.

"script": {
    "type": "nested",
    "properties": {
        "name": {
            "type": "keyword"
        },
        "age": {
            "type": "integer"
        }
    }
}

and sample document below

PUT /btest/_create/1
{
  "script": [
    {
      "name": "john",
      "age": 14
    }
  ]
}

PUT /btest/_create/2
{
  "script": [
    {
      "name": "tt",
      "age": 14
    },
    {
      "name": "jj",
      "age": 17
    },
    {
      "name": "tim",
      "age": 34
    }
  ]
}

PUT /btest/_create/3
{
  "script": [
    {
      "name": "john",
      "age": 42
    },
    {
      "name": "jj",
      "age": 12
    }
  ]
}

and use max aggregation for get max ages :

GET /btest/_search
{
  "query": {
    "nested": {
      "path": "script",
      "query": {
        "match": {
          "script.name": "john"
        }
      }
    }
  },
  "aggs": {
    "age": {
      "nested": {
        "path": "script"
      },
      "aggs": {
        "script_age": {
          "filter": {
            "match": {
              "script.name": "john"
            }
          },
          "aggs": {
            "length": {
              "max": {
                "field": "script.age"
              }
            }
          }
        }
      }
    }
  }
}

but it returns all matched "script.name": "john".

i want to get document only max age john.

should I use aggregation to get this document?

or is there a way to use a query similar to max without aggregation for nested field?

CodePudding user response:

According to your requirement, you need to fetch only those documents that match with name john. This can be achieved in the query section using a nested query with match query.

Now, to get the document having max-age (with name john) you can perform top hits aggregation with sort on script.age field.

{
    "size": 0,
    "query": {
        "nested": {
            "path": "script",
            "query": {
                "match": {
                    "script.name": "john"
                }
            }
        }
    },
    "aggs": {
        "nested-agg": {
            "nested": {
                "path": "script"
            },
            "aggs": {
                "by_age": {
                    "top_hits": {
                        "sort": [
                            {
                                "script.age": {
                                    "order": "desc"
                                }
                            }
                        ],
                        "size": 1
                    }
                }
            }
        }
    }
}

The search response will be

"aggregations": {
        "nested-agg": {
            "doc_count": 3,
            "by_age": {
                "hits": {
                    "total": {
                        "value": 3,
                        "relation": "eq"
                    },
                    "max_score": null,
                    "hits": [
                        {
                            "_index": "71081556",
                            "_type": "_doc",
                            "_id": "3",
                            "_nested": {
                                "field": "script",
                                "offset": 0
                            },
                            "_score": null,
                            "_source": {
                                "name": "john",
                                "age": 42
                            },
                            "sort": [
                                42
                            ]
                        }
                    ]
                }
            }
        }
    }

Option 2

You can use sort with the nested query, to get the document having max age

{
    "size": 1,
    "sort": [
        {
            "script.age": {
                "order": "desc",
                "nested": {
                    "path": "script",
                    "filter": {
                        "term": {
                            "script.name": "john"
                        }
                    }
                }
            }
        }
    ]
}

But in this case, the response contains the entire document, instead of only the matching document

"hits": [
            {
                "_index": "71081556",
                "_type": "_doc",
                "_id": "3",
                "_score": null,
                "_source": {
                    "script": [
                        {
                            "name": "john",
                            "age": 42
                        },
                        {
                            "name": "jj",
                            "age": 12
                        }
                    ]
                },
                "sort": [
                    42
                ]
            }
        ]
  • Related