ElasticSearch:从无痛脚本中的嵌套字段计算arcDistance

时间:2017-04-04 16:14:10

标签: elasticsearch scripting elasticsearch-painless

我需要在Painless脚本中计算弧距,但在这种情况下还没有找到访问geo API的方法,即:

  • 第一个点作为参数传递给脚本 - 这意味着我只获得原始值
  • 从嵌套文档中读取第二个点 - 这意味着我无法使用doc[myGeoField].value API
  • 读取该字段

在这两种情况下,我都无法实例化org.elasticsearch.index.fielddata.ScriptDocValues.GeoPoints,这样我就可以访问.arcDistance()方法。

我也无法使用Painless中不是whitelistedorg.elasticsearch.common.geo.GeoUtils课程。

在脚本中是否还有其他计算弧距的选项?

注意:由于这里解释的原因太长,我为此用例使用脚本 - 在查询/过滤器中执行此操作不是一种选择。< / em>的

2 个答案:

答案 0 :(得分:2)

你想要做的事情似乎是不可能的,因为Elastic的设计选择很差。

我试图做同样的事情(仅限于planeDistance),最后在Painless中实现了planeDistance。

似乎arcDistance和planeDistance等方法莫名其妙地仅在GeoPoints类中实现,而不是在GeoPoint中实现,尽管它更有意义。此外,这些方法only work for the first element位于GeoPoints列表中。

我真的希望有人可以纠正我,虽然我对无痛的经历一直很痛苦。如果你不希望经常改变它,我建议你选择更成熟的东西,比如Java插件。无痛是调试的痛苦,完全缺乏工具,并且没有任何文档。他们也弃用了Groovy和Python,好像无痛是一个不错的替代品。

尽管如此,这里是以英里为单位的距离代码,为了完成(planeDistance的版本,如果你不需要非常准确的距离,请使用它):

double lat1 = location1.lat;
double lon1 = location1.lon;
double lat2 = location2.lat;
double lon2 = location2.lon;
double to_radian = 0.01745329251; /* PI / 180 */
double earth_radius_in_miles = 3959;

double x = (lon2 - lon1) * to_radian * Math.cos((lat2 + lat1) / 2.0 * to_radian);
double y = (lat2 - lat1) * to_radian;
double distanceInMiles = Math.sqrt(x * x + y * y) * earth_radius_in_miles;

答案 1 :(得分:0)

我通过 inner_hits 解决了此问题,请参见以下查询:

mydf.set_index(['a','b','Time'], inplace=True)

# Get Index level values
a = mydf.index.get_level_values('a')
b = mydf.index.get_level_values('b')
t = mydf.index.get_level_values('Time')

# Apply index-based masks
mydf['GRP'] = 'same'
mydf.loc[(a < 5) & (b < 0.5) & (t < day_2), 'GRP'] = 'less'
mydf.loc[(a < 5) & (b > 0.5) & (t > day_1), 'GRP'] = 'more'
mydf.reset_index(drop=False, inplace=True)
mydf

   a         b       Time   GRP
0  0  0.550149 2018-10-14  same
1  1  0.889209 2018-10-15  same
2  2  0.845740 2018-10-16  same
3  3  0.340310 2018-10-17  less
4  4  0.613575 2018-10-18  same
5  5  0.229802 2018-10-19  same
6  6  0.013724 2018-10-20  same
7  7  0.810413 2018-10-21  same
8  8  0.897373 2018-10-22  same
9  9  0.175050 2018-10-23  same

下面是一个响应示例:

{
    "query": {
        "nested": {
            "path": "campi",
            "query": {
                "query_string": {
                    "query": "*"
                }
            },
            "inner_hits": {
                "script_fields": {
                    "distanceInMeters": {
                        "script": {
                            "inline": "!doc['campi.location'].empty ? doc['campi.location'].arcDistance(params.lat, params.lon) : 0",
                            "lang": "painless",
                            "params": {
                                "lon": -43.9207766,
                                "lat": -19.910621
                            }
                        }
                    }
                }
            }
        }
    }
}