gpt4 book ai didi

Elasticsearch:根据类型对不同字段进行排序

转载 作者:行者123 更新时间:2023-11-29 02:51:56 24 4
gpt4 key购买 nike

我的索引中有两种类型(EventCity),我试图按日期对它们进行排序。但是,每种类型的日期字段名称都不同:对于 Event该值在 updated_at 中字段和 City日期在 update_at 中其 city_events 的嵌套对象之一中的字段嵌套对象数组(注意通过 region_id 过滤)。

我试过像这样指定排序数组中的每个字段:

  "sort": [
{
"city_events.updated_at": {
"order": "desc",
"nested_path": "city_events",
"nested_filter": {
"term": {
"city_events.region_id": 1
}
}
}
},
{
"updated_at": "desc"
}
]

但不幸的是,这并没有将这两种类型混合在一起。相反,它首先对所有 Cities 进行排序通过他们的嵌套 city_events.updated_at字段,然后附加所有 Events在底部按他们的 updated_at 排序 field 。如何将两者混合并分类?

作为替代解决方案,我尝试仅按嵌套的 city_events.updated_at 排序字段并指定 "missing": "updated_at" , 然而那抛出一个 "number_format_exception"尽管两个字段的格式相同,但仍然出错:

{
"error": {
"root_cause": [
{
"type": "number_format_exception",
"reason": "For input string: \"updated_at\""
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query_fetch",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "events_1461095196252",
"node": "sYQstSw_SN62ojmXgGjPlg",
"reason": {
"type": "number_format_exception",
"reason": "For input string: \"updated_at\""
}
}
]
},
"status": 400
}

更新 1:基于 the answer by Andrei Stefan下面我尝试开发一个循环遍历 city_events 的 groovy 脚本对于每个 City选择具有匹配项的文件 region_id然后返回 city_eventupdated_at评分值,但在访问脚本中的嵌套字段时遇到问题:https://stackoverflow.com/questions/36781476/elasticsearch-access-fields-inside-array-of-nested-objects-in-a-groovy-script

最佳答案

尝试基于脚本 的排序,您需要您的嵌套 字段具有include_in_parent: true 才能在脚本中访问:

    "city_events": {
"type": "nested",
"include_in_parent": true,
"properties": {
"updated_at": {
"type": "date"
}
}
}

排序部分:

  "sort": {
"_script": {
"type": "number",
"script": {
"inline": "if (doc['_type'].value=='Event') return doc['updated_at'].date.getMillis(); else if (doc['_type'].value=='City') return doc['city_events.updated_at'].date.getMillis()",
"lang": "groovy"
},
"order": "desc"
}
}

后期编辑

即使我将 city_events.region_id==1 条件添加到 Groovy 脚本中,也不会感受到 Elasticsearch,这将是纯粹的 Groovy 编程,而不是 Elasticsearch 的强大功能。

我尝试过其他方法(全部在 ES 2.3.1 中):

  • copy_to 从常规 updated_at 字段到 Event 内的 nested 字段,以便常规 嵌套 排序对所有类型执行。这没有用。
  • 即使 copy_to 会起作用,Elasticsearch 也不会匹配 "term": {"city_events.region_id": 1}(如 region_idEvent 中不存在)来自 Event 类型的 sort 部分,对于这些值将使用 - 9223372036854776000 而不是实际日期(该值来 self 执行的测试)。
  • 也在 Event 中使用 nested 字段,并在索引时将 updated_at 放入该嵌套字段中。由于与上面的尝试 #2 相同的原因,这将不起作用:Event 中也必须有一个 region_id,以便 nested sort 部分的过滤器将适用于两种 类型。

作为处理此问题的正确方法,我的建议是重新考虑一下数据结构,以便排序部分(至少)将遵循 Elasticsearch 的处理方式事物。您的类型称为 CityEvent,在 City 中您有一个(嵌套的)city_events 列表。不能在 City 中包含 Event 并在每个城市复制事件的详细信息吗?这不一定是规范化的 RDB 数据结构。相反,ES 对非规范化数据更满意。


为了完整起见,但我不推荐这样做:

  "sort": {
"_script": {
"type": "number",
"script": {
"inline": "if (doc['_type'].value=='Event') return doc['updated_at'].date.getMillis(); else if (doc['_type'].value=='City') {for(nestedObj in _source.city_events) {if(nestedObj.region_id==1) return nestedObj.updated_at.toLong();}}",
"lang": "groovy"
},
"order": "desc"
}
}

请注意,我没有在上面的 Groovy 脚本中进行所有正确的检查(例如,检查文档中是否确实存在嵌套对象)。

关于Elasticsearch:根据类型对不同字段进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36727898/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com