ElasticSearch范围查询

时间:2018-09-25 09:49:32

标签: elasticsearch

我通过使用以下映射创建了索引:

put test1
{
    "mappings": {
        "type1": {
            "properties": {
                "age": {
                    "type": "text",
                    "fields": {
                        "raw": {
                            "type": "keyword",
                            "ignore_above": 32766
                        }
                    }
                }
            }
        }
    }
}

将以下文档添加到索引中:

PUT test1/type1/1/_create
{
  "age":50
}

PUT test1/type1/2/_create
{
  "age":100
}

PUT test1/type1/3/_create
{
  "age":150
}

PUT test1/type1/4/_create
{
  "age":200
}

我已经使用以下范围查询来获取结果:

GET test1/_search
{
    "query": {
        "range" : {
            "age" : {
                "lte" : 150
            }
        }
    }
}

它给了我以下答复:

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "test1",
        "_type": "type1",
        "_id": "2",
        "_score": 1,
        "_source": {
          "age": 100
        }
      },
      {
        "_index": "test1",
        "_type": "type1",
        "_id": "3",
        "_score": 1,
        "_source": {
          "age": 150
        }
      }
    ]
  }
}

以上未显示年龄为50的文档的响应仅显示年龄为100和150。由于50也小于200。这有什么问题? 谁能帮助我获得有效的结果? 在我的模式年龄字段中输入文本,我不想更改它。

如何获得有效结果?

3 个答案:

答案 0 :(得分:2)

由于年龄字段类型为文本,因此范围查询使用字母顺序。因此结果是正确的:

  • “ 100” <“ 150”
  • “ 150” =“ 150”
  • “ 50”>“ 150”

如果仅在age字段中提取数字,则应将age字段类型更改为number,或添加另一个内部字段作为数字,就像处理{{1 }}内部字段。

答案 1 :(得分:1)

更新:已在本地系统上测试,并且可以正常运行。

注意:理想情况下,您希望映射正确无误,但是如果没有其他选择,而且您不是决定映射的人,那么您仍然可以通过遵循此步骤来实现。

从ES版本6.3开始,请尝试此操作。

 GET test1/type1/_search
    {
        "query": {
            "bool" : {
                "must" : {
                    "script" : {
                        "script" : {
                            "source": "Integer.parseInt(doc['age.raw'].value) <= 150",
                            "lang": "painless"
                         }
                    }
                }
            }
        }
    }

参考来源:

https://www.elastic.co/guide/en/elasticsearch/reference/6.3/query-dsl-script-query.html

https://discuss.elastic.co/t/painscript-script-cast-string-as-int/97034

答案 2 :(得分:0)

您在映射中的字段年龄的类型设置为文本。这就是为什么它在50> 150的情况下进行字典排序。请使用长数据类型。 https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html