【问题标题】:Elasticsearch: Product-variant-price modelling and query problemElasticsearch:产品变体价格建模和查询问题
【发布时间】:2019-06-02 19:25:50
【问题描述】:

我想使用 Elasticsearch 来提高电子商务解决方案中产品搜索的性能 (duh)。我们有一个数据模型,其中一个产品可以有多个变体,每个变体可以有一个或多个价格(有时价格相当可观)。

用户,查询时间,选择是否要返回产品或变体,并且只应返回一个价格(最低有效价格,每个价格都有许多字段,如有效从始至终和有效客户组)。

我的第一种方法是对产品/变体进行非规范化并将价格作为嵌套字段,但这很慢,而且我在排序时遇到了一些问题(我认为是价格,但我现在不知道确切的细节)。

第二种方法是完全非规范化,因此所有产品/变体/价格组合都表示为一个文档。这种方法要快得多(显然),我可以聚合 productIdvariantId 并获得最低价格,但问题是我无法对非数字或非聚合字段的聚合进行排序。

非规范化文档(productIdvariantId 是关键字字段,price 是数字,validFrom/-To 是日期,其余是文本):

[
  {
    "productId": "111-222-333",
    "variantId": "aaa-bbb-ccc",
    "product_title": "Mega-product",
    "product_description": "This awesome piece of magic will change your life",
    "variant_title": "Green mega-product",
    "variant_description": "Behold the awesomeness of the green magic mega-product",
    "color": [
      "blue",
      "green"
    ],
    "brand": "DaBrand",
    "validFrom": "2019-06-01T00:00:00Z",
    "validTo": null,
    "price": 399
  },
  {
    "productId": "111-222-333",
    "variantId": "aaa-bbb-ddd",
    "product_title": "Mega-product",
    "product_description": "This awesome piece of magic will change your life",
    "variant_title": "Blue mega-product",
    "variant_description": "Behold the awesomeness of the blue magic mega-product",
    "color": [
      "blue",
      "green"
    ],
    "brand": "DaBrand",
    "validFrom": "2019-06-01T00:00:00Z",
    "validTo": null,
    "price": 499
  },
  {
    "productId": "111-222-333",
    "variantId": "aaa-bbb-ddd",
    "product_title": "Mega-product",
    "product_description": "This awesome piece of magic will change your life",
    "variant_title": "Blue mega-product",
    "variant_description": "Behold the awesomeness of the blue magic mega-product",
    "color": [
      "blue",
      "green"
    ],
    "brand": "DaBrand",
    "validFrom": "2019-06-05T00:00:00Z",
    "validTo": "2019-06-10T00:00:00Z",
    "price": 399
  }
]

我对汇总价格进行排序的工作查询示例。

{
    "size": 1,
    "sort": {
        "product_name_text_en.keyword": "asc"
    },
    "query": {
        // All the query and filtering
    },
    "aggs": {
        "by_product_id": {
            "terms": {
                "field": "product_id_string",
                "order": {
                    "min_price": "desc"
                }
            },
            "aggs": {
                "min_price": {
                    "min": {
                        "field": "price_decimal"
                    }
                }
            }
        }
    }
}

但是,使用这种方法我找不到对文档字段进行排序的方法。可以(我认为)使用bucket_sort 对数字、布尔值和日期字段进行排序,但我需要能够对例如品牌或标题字段(它们是文本)进行排序。如果可以在 top_hits 聚合上order,我将免费回家,但不幸的是,我从文档中了解到这是不可能的(我也尝试过以确保)。

谁能指导我找到更好的解决方案?我不介意我是否必须分两步进行查询,但要使该工作用于排序,我可能需要使用一些不同的“文档类型”,例如 Product、Variant、ProductPrice 和 VariantPrice,具体取决于请求排序。我并没有走得太远,所以改造肯定会摆在桌面上,我考虑过使用连接字段,但我不确定这是否有效。

由于产品和变体(和价格)的数量可能很大——一百万种产品肯定会摆在桌面上,我认为我在从查询中获取 Id 时会遇到问题(例如过滤品牌和按标题排序)和然后将它们发送到 get-best-price-query 中。

【问题讨论】:

    标签: elasticsearch modeling


    【解决方案1】:

    我在阅读另一个案例的文档时偶然发现了这一点。当我发现Field collapsing 时,一切都变得非常简单。我觉得我应该知道这件事......

    索引与我最初的问题具有相同的模型,但查询变得更加简单:

    {
      "size": 10,
      "query": {
        // filter/match stuff, including filtering valid prices.
      },
      "collapse": {
        "field": "productId",
        "inner_hits": {
          "name": "least_price",
          "collapse": {
            "field": "price"
          },
          "size": 1,
          "sort": [
            {
              "price": "asc"
            }
          ]
        }
      },
      "sort": [
        {
          "brand.keyword": "asc"
        }
      ]
    }
    

    要返回变体而不是产品,我只是在 variantId 上折叠

    折叠基于productIdvariantIdleast_price 用于inner_hits 返回符合我的条件的文档中价格最低的文档(asc 按价格排序并选择第一个) .像魅力一样工作。

    【讨论】:

    • 谢谢!这正是我正在寻找的。不幸的是,spring-data-elasticsearch 还不支持字段折叠。你找到其他选择了吗?
    • 不,很遗憾没有。我还发现它并没有解决我的整个用例,按价格降序排序不起作用,因为排序发生在字段折叠之前。这可能是其他问题,但它们是可以处理的边缘情况。对于价格降序排序,我需要先进行汇总。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 2019-07-09
    • 2017-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多