ElasticSearch 聚合 + 在 NonNumric 字段中排序 5.3

ElasticSearch Aggregation + Sorting in on NonNumric Field 5.3

我想聚合不同字段的数据,还想获取根据名称排序的时尚的聚合数据。

我的数据是:

{
    "_index": "testing-aggregation",
    "_type": "employee",
    "_id": "emp001_local000000000000001",
    "_score": 10.0,
    "_source": {
        "name": [
            "Person 01"
        ],
        "groupbyid": [
            "group0001"
        ],
        "ranking": [
             "2.0"
        ]
    }
},
{
    "_index": "testing-aggregation",
    "_type": "employee",
    "_id": "emp002_local000000000000001",
    "_score": 85146.375,
    "_source": {
        "name": [
            "Person 02"
        ],
        "groupbyid": [
            "group0001"
        ],
        "ranking": [
             "10.0"
        ]
    }
},
{
    "_index": "testing-aggregation",
    "_type": "employee",
    "_id": "emp003_local000000000000001",
    "_score": 20.0,
    "_source": {
        "name": [
            "Person 03"
        ],
        "groupbyid": [
            "group0002"
        ],        
        "ranking": [
             "-1.0"
        ]
    }
},
{
    "_index": "testing-aggregation",
    "_type": "employee",
    "_id": "emp004_local000000000000001",
    "_score": 5.0,
    "_source": {
        "name": [
            "Person 04"
        ],
        "groupbyid": [
            "group0002"
        ],
        "ranking": [
             "2.0"
        ]
    }
}

我的查询:

{
    "size": 0,
    "query": {
        "bool": {
            "must": [
                {
                    "query_string": {
                        "query": "name:emp*^1000.0"
                    }
                }
            ]
        }
    },
    "aggs": {
        "groupbyid": {
            "terms": {
                "field": "groupbyid.raw",
                "order": {
                    "top_hit_agg": "desc"
                },
                "size": 10
            },
            "aggs": {
                "top_hit_agg": {
                    "terms": {
                        "field": "name"
                    }
                }
            }
        }
    }
}

我的映射是:

{
    "name": {
        "type": "text",
        "fielddata": true,
        "fields": {
            "lower_case_sort": {
                "type": "text",
                "fielddata": true,
                "analyzer": "case_insensitive_sort"
            }
        }
    },
    "groupbyid": {
        "type": "text",
        "fielddata": true,
        "index": "analyzed",
        "fields": {
            "raw": {
                "type": "keyword",
                "index": "not_analyzed"
            }
        }
    }
}

我正在根据分组记录的相关性平均值获取数据。现在,我想要的是第一个俱乐部基于 groupid 的记录,然后在每个桶中根据名称字段对数据进行排序。

我想在一个字段上分组,在那个分组桶之后,我想在另一个字段上排序。这是示例数据。

还有其他字段,例如 created_on、updated_on。我还想根据该字段获取排序数据。还按字母顺序分组获取数据。

我想对非数字数据类型(字符串)进行排序。我可以做数字数据类型。

我可以为排名字段做到这一点,但不能为名称字段做到这一点。它给出了以下错误。

Expected numeric type on field [name], but got [text]; 

你问的有点多,我尽量依次回答。

第 1 步:按相关性对存储桶进行排序

I am getting data based on the average of the relevance of grouped records.

如果这是您尝试执行的操作,那么您编写的聚合不会执行此操作。术语聚合默认按每个桶中文档的数量降序对桶进行排序。要按 "average relevance" 对组进行排序(我将其解释为 "average _score of documents in the group"),您需要在分数上添加一个子聚合并按此对术语聚合进行排序:

"aggregations": {
  "most_relevant_groups": {
    "terms": {
      "field": "groupbyid.raw",
      "order": {
        "average_score": "desc"
      }
    },
    "aggs": {
      "average_score": {
        "avg": {
          "script": {
            "inline": "_score",
            "lang": "painless",
          }
        }
      }
    }
  }
}

第 2 步:按姓名对员工进行排序

Now, what I wanted is the first club the records based on the groupid and then in each bucket sort the data based on the name field.

要对每个存储桶中的文档进行排序,您可以使用 top_hits 聚合:

"aggregations": {
  "most_relevant_groups": {
    "terms": {
      "field": "groupbyid.raw",
      "order": {
        "average_score": "desc"
      }
    },
    "aggs": {
      "employees": {
        "top_hits": {
          "size": 10,  // Default will be 10 - change to whatever
          "sort": [
            {
              "name.lower_case_sort": {
                "order": "asc"
              }
            }
          ]
        }
      }
    }
  }
}

第 3 步:将它们放在一起

将以上两者放在一起,以下聚合应该满足您的需求(请注意,我使用 function_score 查询来模拟基于排名的 "relevance" - 您的查询可以是任何需要的成为产生您需要的任何相关性的任何查询):

POST /testing-aggregation/employee/_search
{
  "size": 0,
  "query": {
    "function_score": {
      "functions": [
        {
          "field_value_factor": {
            "field": "ranking"
          }
        }
      ]
    }
  },
  "aggs": {
    "groupbyid": {
      "terms": {
        "field": "groupbyid.raw",
        "size": 10,
        "order": {
          "average_score": "desc"
        }
      },
      "aggs": {
        "average_score": {
          "avg": {
            "script": {
              "inline": "_score",
              "lang": "painless"
            }
          }
        },
        "employees": {
          "top_hits": {
            "size": 10,
            "sort": [
              {
                "name.lower_case_sort": {
                  "order": "asc"
                }
              }
            ]
          }
        }
      }
    }
  }
}