【问题标题】:Complex query in elasticsearchelasticsearch中的复杂查询
【发布时间】:2020-04-06 22:02:05
【问题描述】:

我有一个包含折扣价格的文档结构。仅当满足折扣的所有条件时才会应用折扣。
我努力找出一个可以解决下面提到的用例的查询,但我想我最终将不得不使用脚本功能。有没有一种方法可以在不编写脚本的情况下为以下用例构建查询?

{
  "name": "Brown Teddy With Hat",
  "prices": {
    "basePrice": {
      "price": 3000, // actual price
      "discounts": [
        { "price": -10, "conditions": ["value1"] },
        { "price": -20, "conditions": ["value5", "value7"] }, // two conditions 
        { "price": -30, "conditions": ["value6"] },
        { "price": -40, "conditions": [] } // no conditions
      ]
    },
    "installmentPrice": {...} // ignore for now
  }
}

我想汇总满足条件的所有折扣。将有一个输入数组,其中包含一些条件值,例如 [value5, value6, value1]。折扣条件应该是输入数组的子集。
在上面的示例中:将应用折扣 -10、-30 和 -40。我想从实际价格(3000)中减去折扣,然后按折扣价排序。

我尝试了terms_set 查询,但它适用于简单的情况,例如具有数组字段的文档并将输入与该数组进行匹配,但在我的情况下,折扣是多个嵌套的,terms_set 无法正常工作。

Elasticsearch 版本 - 6.6.1
没有帮助的参考:
https://discuss.elastic.co/t/subsets/46488
https://discuss.elastic.co/t/match-all-terms-in-document-array/24793

【问题讨论】:

    标签: elasticsearch elasticsearch-aggregation elasticsearch-6


    【解决方案1】:

    终于,我花了一些时间后能够使用 terms_set。
    我还在折扣中添加了一个字段,它是 requiredMatch。
    对我来说, requiredMatch 字段的值等于条件数组的长度。我们也可以避免添加这个字段,使用脚本来访问条件数组的长度。
    条件数组为空的情况不起作用。我将通过始终向条件数组和输入数组添加“默认”值来破解它。因此,空条件将始终按预期匹配。

    这是解决我的用例的查询:

    {
      "aggs": {
        "sorted_by_price": {
          "aggs": {
            "nested_discounts_aggs": {
              "nested": {
                "path": "prices.basePrice.discounts"
              },
              "aggs": {
                "conditions_set_match": {
                  "filter": {
                    "terms_set": {
                      "prices.basePrice.discounts.conditions": {
                        "terms": [
                          "facebook",
                          "agreement12",
                          "bestxl",
                          "useless",
                          "magenta"
                        ],
                        "minimum_should_match_field": "prices.basePrice.discounts.requiredMatch"
                      }
                    }
                  },
                  "aggs": {
                    "finalPrice": {
                      "sum": {
                        "field": "prices.basePrice.discounts.price"
                      }
                    }
                  }
                }
              }
            }
          },
          "terms": {
            "field": "_id",
            "order": {
              "nested_discounts_aggs>conditions_set_match>finalPrice": "desc"
            },
            "size": 5
          }
        }
      }
    }
    

    新文档如下所示:

    {
      "name": "Brown Teddy With Hat",
      "prices": {
        "basePrice": {
          "discounts": [
            { "price": 3000, "conditions": ["default"], "requiredMatch": 1 }, // actual price
            { "price": -10, "conditions": ["value1"], "requiredMatch": 1 },
            { "price": -20, "conditions": ["value5", "value7"], "requiredMatch": 2 }, // two conditions 
            { "price": -30, "conditions": ["value6"], "requiredMatch": 1 },
            { "price": -40, "conditions": ["default"], "requiredMatch": 1 } // no conditions
          ]
        },
        "installmentPrice": {...} // ignore for now
      }
    }
    

    剩下的唯一部分就是在折扣中增加价格。我将通过删除价格字段并包括实际价格作为具有正值的折扣来实现这一点。请注意折扣有负值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      • 1970-01-01
      • 2017-05-21
      相关资源
      最近更新 更多