elasticsearch - ElasticSearch聚合+在非数值字段5.3上排序

标签 elasticsearch search elastic-stack elasticsearch-5 elasticsearch-aggregation

我想将数据汇总到另一个字段中,也想根据名称以排序的方式获取汇总的数据。

我的数据是:

{
    "_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.



如果这是您要尝试执行的操作,则不是您编写的聚合正在执行的操作。术语汇总默认情况下按每个存储区中的文档数降序对存储区进行排序。要按“平均相关性”(我将其解释为“该组中文档的平均_score”)对组进行排序,您需要在得分上添加一个子聚合,然后对术语聚合进行排序:
"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查询来基于排名模拟“相关性”-您的查询可以是任意查询,而只要是能够产生所需相关性的查询即可) :
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"
                }
              }
            ]
          }
        }
      }
    }
  }
}

关于elasticsearch - ElasticSearch聚合+在非数值字段5.3上排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60539380/

相关文章:

elasticsearch - 索引模板的部分更新

ruby-on-rails - Twitter API- Rails 未定义方法 `name' 为 nil :NilClass

java - 在 Elasticsearch 上创建自定义 CRUD

elasticsearch - ElasticSearch中的聚合操作

elasticsearch - ElasticSearch 7.2.0(启用 x-pack 时)的默认用户名和密码是什么?

java - 在java中使用curl进行 Elasticsearch 查询

具有不同权重的多字段 Elasticsearch 补全建议器

elasticsearch - Elasticsearch,对全文字符串进行过滤

php - 让 PHP 搜索一切

c++ - 从单词列表构造回文