Elasticsearch:如何根据具有最大/最小值

时间:2016-07-22 18:01:55

标签: elasticsearch elasticsearch-query

我有很多包含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] }
}

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

1 个答案:

答案 0 :(得分:0)

你要求的是range,这隐含着是或否的问题。实际上奇怪的是,除了作为一个助推器之外,甚至比其他任何东西都要得分(例如:如果它有,然后提高分数,但如果它没有它,那就没关系)。因此,range查询趋势最适合在过滤器上下文中使用。

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

(语法假设ES 2.0)

这对你没有帮助,但这是你做这个请求的更好方法。

至于您要问的内容,您希望根据文档中的原始值进行加权。这是 less 直接向前,因为值是一个数组,其值可能超出范围而且它不是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
            }
          }
        }
      ]
    }
  }
}

你应该not be using inline Groovy scripts in production(改为使用基于文件的脚本),但上面的方法可行。