ElasticSearch数据结构和查询

时间:2018-04-10 22:21:28

标签: elasticsearch

我有下一个模型结构:

Product:
  name: char

Shop:
  location: geo_point

ShopProduct:
  shop: ForeignKey(Shop)
  product: ForeignKey(Product)
  price: double

我需要Product使用ElasticSearch(v5.2)实现搜索。因此,如果用户输入某个产品名称,他将在结果中收到产品名称,最近位置以及最低和最高价格。另外,我需要按名称,位置和价格排序。

我有两个问题:

1。我应该使用哪种映射结构用于ElasticSearch索引,以按地点/价格排序按产品进行搜索?

目前,我有两个指数,第一个是产品,第二个是商店。产品索引具有“嵌套”数据类型到商店位置。我已添加它,因为我需要按位置和价格实现排序功能。我觉得这不是一个好主意,但我不确定应该使用哪种数据结构来实现排序。此外,我正在考虑亲子关系,但我认为它不适合我的数据 - 在文档中提到它应该用于一些父对象和许多孩子。

    # Product Index
    "mappings": {
        "product": {
            "properties": {
                "name": {"type": "string"}
                "locations": {
                    "type": "nested",
                    "properties": {
                        "location": {"type": "geo_point"},
                        "price": {"type": "float"}
                    }
                }
            }
        }
    }

    # Shop Index
    "mappings": {
        "shop": {
            "properties": {
                "location": {"type": "geo_point"},
                "shop_products": {
                    "type": "nested",
                    "properties": {
                        "product_id": {"type": "long"},
                        "product_name": {"type": "string"},
                        "price": {"type": "float"}
                    }
                },
            }
        }
    }

2。如何获得每种产品的最近位置和最低/最高价格?

我尝试使用带有这样的脚本的script_fields来计算它,但后来注意到ElasticSearch不允许我访问嵌套对象。所以,这个脚本不起作用。

    "script_fields": {
        "locations": {
            "script": {
                "lang": "painless",
                "params": {
                    'lat': 50,
                    'lon': -120
                },
                "inline": """
                    def locations = params._source.locations; // I've also try doc['locations.location'].value
                    if (locations.length > 0) {
                        distance = locations[0].location.planeDistanceWithDefault(params.lat, params.lon, 0)
                        for (int i = 1; i < locations.length; ++i) {
                            if (distance > locations[i].location.planeDistanceWithDefault(params.lat, params.lon, 0)) {
                                distance = locations[i].location.planeDistanceWithDefault(params.lat, params.lon, 0)
                            }
                        }
                    }
                    return distance;
                """
            }
        }
    }

然后,我尝试使用聚合来计算最低/最高价格和最近的位置。聚合对我有用,但ElasticSearch对aggs没有任何分页,并且有一个issue

    "aggs": {
    "product": {
        "terms": {
            "field": "name"
        },
        "aggs": {
            "prices": {
                "nested": {
                    "path": "locations"
                },
                "aggs": {
                    "price": {
                        "stat": {
                            "field": "locations.price"
                        }
                    },
                    "min_distance": {
                        "min": {
                            "script": {
                                "lang": "painless",
                                "inline":  """
        if (params.lat != 0 && params.lon != 0){
            def distance = doc['locations.location'].planeDistanceWithDefault(params.lat, params.lon, 0);
            if (distance !=0){
                return distance;
            }
        }
    """,
                    "params": {
                        'lat': 50,
                        'lon': -120
                    }
                }
            }
        }
    }}}}}

在我的例子中,每个产品可以有大约30个商店出售它。所以,我不想在结果中返回所有可用的位置,只是最近或在交付区域。这就是为什么我要单独查询以获取每个产品的位置。

提前谢谢。

0 个答案:

没有答案