0

我有许多文档包含一个rate属性,该属性是一个包含可接受率的最小/最大范围的数组。

{ "rate": [250, 700] }

我现在想执行提供另一个范围的查询,例如:

{
  "bool": {
     "must": [
       "range": {
         "rate": { "from": 100, "to": 500 }
       }
     ]
  }
}

这工作正常,并且总是返回具有至少一个在我想要的范围内提供的值的值。

但是,对于所有结果,分数是相同的。值是否与文档上的值相同或者它只是达到几个数字的范围都没有关系。如下所示:

{
  "_id": "one",
  "_score": 1",
  "_source": { "rate": [250,750] }
},
{
  "_id": "two",
  "_score": 1",
  "_source": { "rate": [200,350] }
},
{
  "_id": "three",
  "_score": 1",
  "_source": { "rate": [500,750] }
}

有没有办法改善范围搜索提供另一个这样的范围?

4

1 回答 1

0

您要求 a range,这隐含的是一个是或否的问题。甚至除了作为助推器之外的任何东西都对它进行评分实际上很奇怪(例如:如果它有,那么就提高分数,但如果它没有它,那没关系)。因此,range查询往往最好在过滤器上下文中使用。

"query": {
  "bool": {
    "filter": [
      {
        "range": {
          "rate": { "gte": 100, "lte": 500 }
        }
      }
    ]
  }
}

(语法假定 ES 2.0)

这并不能真正帮助您,但它是执行您正在执行的请求的更好方法。

至于您要问什么,您想根据文档中的原始值进行加权。这不那么直截了当,因为该值是一个数组,其值可能超出范围并且它不是一个nested对象,因此它始终被视为一个数组(这意味着您需要手动重新排除被忽略的结果)。

完全自定义评分需要脚本(本机或其他),这可以通过脚本评分轻松完成。

值是否与文档上的值相同或者它只是达到几个数字的范围都没有关系。

我实际上不明白第一部分是什么意思:你想要一个匹配“重量”更少还是更多?与边缘的距离是否重要?只是匹配重要吗?

我将假设更多匹配更好,无论它们落在范围内的哪个位置:

{
  "query": {
    "bool": {
      "must": {
        "function_score": {
          "functions": [
            {
              "script_score": {
                "script": {
                  "inline": "doc['rate'].values.findAll { it >= gte && it <= lte }.size()",
                  "lang": "groovy",
                  "params": {
                    "gte": 100,
                    "lte": 500
                  }
                }
              }
            }
          ],
          "boost_mode": "replace"
        }
      },
      "filter": [
        {
          "range": {
            "rate": {
              "gte": 100,
              "lte": 500
            }
          }
        }
      ]
    }
  }
}

不应该在生产环境中使用内联 Groovy 脚本(改用基于文件的脚本),但上述方法可以使用。

于 2016-07-24T00:45:39.110 回答