Elasticsearch查询:使用嵌套对象和函数得分乘以最终得分

时间:2014-10-30 11:38:25

标签: elasticsearch

我的文档中包含一些数据和特定的省略列表(请参阅mappingexample data):

我想写一个ES查询,它执行以下操作:

  1. 计算一些"基本"文件得分(查询1):

    {
      "explain": true,
      "query": {
        "bool": {
          "should": [
            {
              "constant_score": {
                "filter": {
                  "term": {
                    "type": "TYPE1"
                  }
                }
              }
            },
            {
              "function_score": {
                "linear": {
                  "number": {
                    "origin": 30,
                    "scale": 20
                  }
                }
              }
            }
          ]
        }
      }
    }
    
  2. 最后根据特定id的省略百分比乘以得分(在我使用的示例中省略了 A "omit.id": "A"的valut)。作为查询2中的演示,我计算了这个乘数。

    {
      "query": {
        "nested": {
          "path": "omit",
          "query": {
            "function_score": {
              "query": {
                "filtered": {
                  "query": {
                    "match_all": {}
                  },
                  "filter": {
                    "term": {
                      "omit.id": "A"
                    }
                  }
                }
              },
              "functions": [
                {
                  "linear": {
                    "omit.percent": {
                      "origin": 0,
                      "scale": 50,
                      "offset": 0,
                      "decay": 0.5
                    }
                  }
                }
              ],
              "score_mode": "multiply"
            }
          }
        }
      }
    }
    
  3. 为实现最终的倍增,我遇到了以下问题:

    • 如果我在嵌套查询中计算线性函数得分(根据我的解释),我不能在function_score查询中使用任何其他字段。
    • 我无法将计算出的分数与封装在嵌套查询中的任何其他function_score相乘。

    我想请求任何建议来解决这个问题。

    请注意,也许我应该摆脱这种嵌套类型并改为使用键值对。例如:

    {
      "omit": {
        "A": {
          "percent": 10
        },
        "B": {
          "percent": 100
        }
      }
    }
    

    但不幸的是会有很多密钥,这会导致巨大的(不断增长的)映射,所以我不喜欢这个选项。

1 个答案:

答案 0 :(得分:2)

至少我找到了一种基于"非嵌套方式的可能解决方案"。可以找到完整的脚本here

我按照问题中的描述修改了省略列表:

"omit": {
  "A": {
    "percent": 10
  },
  "B": {
    "percent": 100
  }
}

此外,我将enabled标志设置为false,以便在映射中没有这些元素:

"omit": {
  "type" : "object",
  "enabled" : false
}

最后一招是将script_score用作function_score的函数,因为只有percent _source.omit.A.percent脚本可以使用{ "query": { "function_score": { "query": { ... }, "script_score": { "lang": "groovy", "script": "if (_source.omit.A){(100-_source.omit.A.percent)/100} else {1}" }, "score_mode": "multiply" } } } 的值:

{{1}}