首页 > 解决方案 > 重用/缓存脚本字段以使用查询的其他部分

问题描述

我正在做一个项目,我们需要显示列表与用户位置的距离。为了显示距离,当输入中给出纬度/经度时,我们使用名为“距离”的脚本字段计算距离

"script_fields" : {
        "distance" : {
            "script" : {
                "lang": "painless",
                "source": "Math.round((doc['location'].planeDistanceWithDefault(params.lat, params.lon, 0) * 0.001) * 100.0) / 100.0",
                "params" : {
                    "lat"  : -33.8152,
                    "lon" : 151.0012
                }
            }
        }
    }

但是,对于相关性搜索,我们希望将最近的列表排名更高,并且我们在函数分数查询中再次计算距离。这是低效的。我已经搜索了互联网以找到解决方案,但没有运气。

有没有办法在查询或过滤或排序的其他部分重用脚本字段?

完整查询:

GET /listings/_doc/_search
{
    "_source" : true,
    "query": {
        "function_score": {
            "score_mode": "sum",
            "query": { "match": {
          "source_id": 1
        } },
            "functions": [
              {
                "script_score": {
                  "script": {
                    "params": {
                      "dealer": {"a": 5, "b": 6},
                      "photo": {"a": 4, "b": 5},
                      "location": {"lat": -33.8152, "lon": 151.0012}
                    },
                    "source": "(doc['location'].planeDistanceWithDefault(params.location.lat, params.location.lon, 1000) * 0.001 < 25 ? 200000 : 0) + (doc['is_dealer'].value == 1 ? Math.pow(params.dealer.a, params.dealer.b) : 0) + (doc['hasPhoto'].value == 1 ? Math.pow(params.photo.a, params.photo.b) : 0)"
                  }
                }
              }
            ]
        }
    },
    "script_fields" : {
        "distance" : {
            "script" : {
                "lang": "painless",
                "source": "Math.round((doc['location'].planeDistanceWithDefault(params.lat, params.lon, 0) * 0.001) * 100.0) / 100.0",
                "params" : {
                    "lat"  : -33.8152,
                    "lon" : 151.0012
                }
            }
        }
    }
}

标签: elasticsearchelastic-stack

解决方案


您正在使用脚本字段计算距离。无法使用脚本字段对结果进行排序,因为脚本字段是在文档排序后计算的,请参见此处

您可以做的是使用Geo Distance Sorting对结果进行排序:

GET /listings/_doc/_search
{
    "_source" : true,
    "query": {
        /* your query */ 
    },
    "script_fields" : {
        "distance" : {
            "script" : {
                "lang": "painless",
                "source": "Math.round((doc['location'].planeDistanceWithDefault(params.lat, params.lon, 0) * 0.001) * 100.0) / 100.0",
                "params" : {
                    "lat"  : -33.8152,
                    "lon" : 151.0012
                }
            }
        }
    },
    "sort" : [
        {
            "_geo_distance" : {
                "location" : {
                    "lat" : -33.8152,
                    "lon" : 151.0012
                },
                "order" : "asc",
                "unit" : "km",
                "mode" : "min",
                "distance_type" : "sloppy_arc"
            }
        }
    ]
}

另请参阅this question,它可能会有所帮助。


推荐阅读