将来自 Kibana 的 Elasticsearch 请求转换为 elasticsearch-dsl

Translating Elasticsearch request from Kibana into elasticsearch-dsl

最近从 AWS Elasticsearch Service(使用 Elasticsearch 1.5.2)迁移到 Elastic Cloud(目前使用 Elasticsearch 5.1.2)。很高兴我做到了,但随着这一变化而来的是更新版本的 Elasticsearch 和更新的 API。努力让我了解请求东西的新方式。以前,我可以或多或少地从 Kibana 的 "Elasticsearch Request Body" 中 copy/paste,调整一些东西,运行 elasticsearch.Elasticsearch.search() 并得到我期望的。

这是我来自 Kibana 的 Elasticsearch 请求正文(为简洁起见,删除了 Kibana 通常插入的一些无关内容):

{
  "size": 500,
  "sort": [
    {
      "Time.ISO8601": {
        "order": "desc",
        "unmapped_type": "boolean"
      }
    }
  ],
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "query": "Message\ ID: 2003",
            "analyze_wildcard": true
          }
        },
        {
          "range": {
            "Time.ISO8601": {
              "gte": 1484355455678,
              "lte": 1484359055678,
              "format": "epoch_millis"
            }
          }
        }
      ],
      "must_not": []
    }
  },
  "stored_fields": [
    "*"
  ],
  "script_fields": {},
}

现在我想使用 elasticsearch-dsl 来做,因为这似乎是推荐的方法(而不是使用 elasticsearch-py)。我如何将以上内容翻译成 elasticsearch-dsl?

这是我目前的情况:

from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search, Q

client = Elasticsearch(
        hosts=['HASH.REGION.aws.found.io/elasticsearch'],
        use_ssl=True,
        port=443,
        http_auth=('USER','PASS')
    )

s = Search(using=client, index="emp*")
s = s.query("query_string", query="Message\ ID:2003", analyze_wildcards=True)
s = s.query("range", **{"Time.ISO8601": {"gte": 1484355455678, "lte": 1484359055678, "format": "epoch_millis"}})
s = s.sort("Time.ISO8601")

response = s.execute()

for hit in response:
    print '%s %s' % (hit['Time']['ISO8601'], hit['Message ID']) 

我上面写的代码没有达到我的预期。得到的结果包括不匹配 "Message\ ID:2003" 的东西,而且它也给了我超出 Time.ISO8601 请求范围的东西。

对 elasticsearch-dsl 和 ES 5.1.2 的处理方式完全陌生,所以我知道我有很多东西要学。我究竟做错了什么?在此先感谢您的帮助!

我现在没有 elasticsearch 运行 但查询看起来像你想要的(你总是可以通过查看 s.to_dict() 看到生成的查询)除了转义 \标志。在原始查询中,它被转义了,但在 python 中,由于不同的转义,结果可能会有所不同。

我强烈建议您的字段中不要有空格,并且使用比 query_string:

更结构化的查询
s = Search(using=client, index="emp*")
s = s.filter("term", message_id=2003)
s = s.query("range", Time__ISO8601={"gte": 1484355455678, "lte": 1484359055678, "format": "epoch_millis"})
s = s.sort("Time.ISO8601")

请注意,我还将 query() 更改为 filter() 以略微加快速度,并在字段名称关键字参数中使用 __ 而不是 .elasticsearch-dsl 会自动将其扩展为 .

希望这对您有所帮助...