ElasticSearch'范围'查询返回不合适的结果

时间:2015-08-04 11:33:48

标签: elasticsearch

让我们来看看这个问题:

{
"timeout": 10000,
"from": 0,
"size": 21,
"sort": [
    {
        "view_avg": {
            "order": "desc"
        }
    }
],
"query": {
    "bool": {
        "must": [
            {
                "range": {
                    "price": {
                        "from": 10,
                        "to": 20
                    }
                }
            },
            {
                "terms": {
                    "category_ids": [
                        16405
                    ]
                }
            }
        ]
    }
}

}

对我正在运行的数据集的此查询应该不返回任何结果(因为所有价格都在100s-1000s范围内)。但是,此查询返回结果,匹配价格为:

"price": "1399.00"
"price": "1299.00"
"price": "1089.00"

等等,等等。任何想法如何修改查询,以便返回正确的结果?

2 个答案:

答案 0 :(得分:3)

我99%确定您的映射是错误的,price声明为string。 Elasticsearch正在使用基于字段类型的不同Lucene范围查询,正如您在其documentation中看到的那样。 TermRangeQuery类型的string与您的输出类似,它使用lexicographical ordering(即1100在10到20之间)。

要测试它,您可以尝试以下映射/搜索:

PUT tests/

PUT tests/test/_mapping
{
    "test": {
        "_source" : {"enabled" : false},
        "_all" : {"enabled" : false},
        "properties" : {
            "num" : {
                "type" : "float", // <-- HERE IT'S A FLOAT
                "store" : "no",
                "index" : "not_analyzed"
            }
        }
    }
}

PUT tests/test/1
{
    "test" : {
        "num" : 100
    }
}

POST tests/test/_search
{
    "query": {
    "bool": {
        "must": [
            {
                "range": {
                    "num": {
                        "from": 10,
                        "to": 20
                    }
                }
            }
        ]
        }
    }
}

Result:

{
   "took": 12,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 0,
      "max_score": null,
      "hits": []
   }
}

如果删除索引并尝试重新创建它,将num类型更改为字符串:

PUT tests/test/_mapping
{
    "test": {
        "_source" : {"enabled" : false},
        "_all" : {"enabled" : false},
        "properties" : {
            "num" : {
                "type" : "string", // <-- HERE IT'S A STRING
                "store" : "no",
                "index" : "not_analyzed"
            }
        }
    }
}

您会看到不同的结果:

{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "tests",
            "_type": "test",
            "_id": "1",
            "_score": 1
         }
      ]
   }
}

答案 1 :(得分:1)

price必须是must工作的数字字段。如果它string它会返回。确保映射是正确的,如果映射是float它将起作用。

您可以使用GET /index_name/_mapping检查索引的映射。

如果您有以下内容(且pricestring):

      "range": {
        "price": {
          "from": 30,
          "to": 40
        }
      }

不应该返回文档,因为1(字符串)在34(字符串)之前,即使在数字上说30小于1399也是如此。