让我们来看看这个问题:
{
"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"
等等,等等。任何想法如何修改查询,以便返回正确的结果?
答案 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
检查索引的映射。
如果您有以下内容(且price
为string
):
"range": {
"price": {
"from": 30,
"to": 40
}
}
不应该返回文档,因为1
(字符串)在3
或4
(字符串)之前,即使在数字上说30小于1399也是如此。