尝试基于脚本的排序,您需要嵌套字段才能在脚本中访问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内的嵌套字段,以便对所有类型执行常规嵌套排序.这没用.
>即使copy_to有效,Elasticsearch也不会匹配“term”:{“city_events.region_id”:1}(因为在事件中不存在region_id)来自Event类型中的排序部分,并且这些值将会使用-9223372036854776000而不是实际日期(这些值来自我执行的测试).
>在Event中使用嵌套字段,在索引时,将updated_at放在此嵌套字段中.这与上述尝试#2的原因相同:在Event中也必须有一个region_id,以便排序部分的嵌套过滤器适用于这两种类型.
作为处理这个问题的正确方法,我建议的是重新考虑一下数据结构,以便排序部分(至少)遵循Elasticsearch的做事方式.您的类型称为城市和事件,在城市内您有一个(嵌套的)city_events列表.您不能在城市中包含活动并在每个城市复制活动的详细信息吗?这不一定是规范化的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脚本中进行所有正确的检查(例如,检查文档中是否存在实际的嵌套对象).