【问题标题】:Elastic search apply boost based on nested field value弹性搜索基于嵌套字段值应用提升
【发布时间】:2021-01-22 18:44:13
【问题描述】:

下面是我的索引文档

 {
  "defaultBoostValue":1.01,
  "boostDetails": [
    {
      "Type": "Type1",
      "value": 1.0001
    },
    {
      "Type": "Type2",
      "value": 1.002
    },
    {
      "Type": "Type3",
      "value": 1.0005
    }
  ]
}

我想根据传递的值应用 boost,所以假设我传递 Type 1,那么 boost 应用的将是 1.0001,如果 Type1 不存在,那么它将使用 defaultBoostValue 下面是我的查询,它工作但很慢,有没有办法进一步优化它

Original question 上面的查询有效,但由于我们使用 _source

很慢
   {
  "query": {
    "function_score": {
      "boost_mode": "multiply",
      "functions": [
          "script_score": {
            "script": {
              "source": """
                double findBoost(Map params_copy) {
                    for (def group : params_copy._source.boostDetails) {
                        if (group['Type'] == params_copy.preferredBoostType ) {
                            return group['value'];
                        }
                    }
                    return params_copy._source['defaultBoostValue'];
                }
                
                return findBoost(params)
              """,
              "params": {
                "preferredBoostType": "Type1"
              }
            }
          }
        }
      ]
    }
  }
}

我已经删除了没有动态映射的条件,如果更改 boostDetails 映射的结构有帮助,那我没问题,但请解释它如何帮助并更快查询如果答案包含,请给出映射类型和修改后的结构修改映射。

【问题讨论】:

    标签: elasticsearch kibana elasticsearch-7


    【解决方案1】:

    使用动态映射(大量字段)

    your original question相比,您似乎调整了文档结构。

    上面的查询被认为是嵌套字段,出于性能原因,这些字段不能轻松在脚本中迭代。话虽如此,上面是一个更慢的解决方法,它访问文档的_source 并迭代其内容。但请记住,不建议在脚本中访问 _source

    如果您的文档不再嵌套,您可以访问所谓的doc values,它更适合查询时访问:

    {
      "query": {
        "function_score": {
          ...
          "functions": [
            {
              ...
              "script_score": {
                "script": {
                  "lang": "painless",
                  "source": """
                    try {
                      if (doc['boost.boostType.keyword'].value == params.preferredBoostType) {
                        return doc['boost.boostFactor'].value;
                      } else {
                        throw new Exception();
                      }
                    } catch(Exception e) {
                      return doc['fallbackBoostFactor'].value;
                    }
                  """,
                  "params": {
                    "preferredBoostType": "Type1"
                  }
                }
              }
            }
          ]
        }
      }
    }
    

    从而加快您的功能得分查询。


    使用有序值列表的替代方法

    由于嵌套迭代很慢并且动态映射会破坏您的索引,您可以将提升存储在每个文档的标准化有序列表中:

    "boostValues": [1.0001, 1.002, 1.0005, ..., 1.1]
    

    并在您构建查询的后端跟踪相应的提升类型的顺序:

    var boostTypes = ["Type1", "Type2", "Type3", ..., "TypeN"]
    

    比如n-hot vectors

    然后,当您构建 Elasticsearch 查询时,您将根据 boostType 查找 boostValues数组索引,并将此数组索引从上面传递给脚本查询'd 访问相应的boostValues doc-value。

    这保证比_source 访问更快。 但要求您始终保持boostTypesboostValues 同步 - 最好只追加(当您添加新的boostTypes 时,列表会在一维中增长)。

    【讨论】:

    • 谢谢,如果索引结构类似于 {boost: {"Type1": 1.00003}, {Type2: 1.222}} 对吗?
    • 是的,应该的。
    • 这需要动态索引,我正在寻找没有动态索引的解决方案。
    • 我已经编辑了问题以匹配原始问题,并添加了指向原始问题的链接
    • 你会有多少种类型?知道吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 2021-07-04
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 1970-01-01
    • 2020-06-14
    相关资源
    最近更新 更多