繁体   English   中英

Python中的Elasticsearch。 如何从搜索中获取关闭整数

[英]Elasticsearch in Python. How to get closes integer from search

我在大型索引数据库上使用elasticsearch。 其中一个查询需要查找整数值和字符串,例如:

s = Search(using=es, index="index1").extra(size=500) \
                        .query("match_phrase", name={"query": "john".casefold()})\
                        .query("match", age="46")

这将搜索包含“John white”和“46”的数据记录。 但是,如果年龄不正确,我想获得一个包含“John white”的记录和最接近“46”的年龄(假设我有这些记录,否则它将不返回任何内容)。

然而,上述查询仅返回年龄记录为“46”的记录。

在SO上已经存在类似的问题: 如何使用弹性搜索中的查询DSL找到最近/最接近的数字

但我不知道如何将JSON合并到我的查询中,因为我使用的是特定的python模块。

一个典型的例子就是我可以在字符串上使用模糊性。 但是我觉得在弹性搜索中,整数的模糊性是不可能的。

我建议使用基于脚本的排序来完成此操作,如下所述: https//www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html#_script_based_sorting

在假设您只匹配名字的情况下工作 - 如果您想要完全匹配名称,我建议使用基于过滤器的匹配。 我在索引中使用了三个不同的“用户”,定义如下:

POST index1/_doc
{
  "name": "John White",
  "age": 46
}

POST index1/_doc
{
  "name": "John White",
  "age": 40
}

POST index1/_doc
{
  "name": "John Black",
  "age": 47
}

我发现使用Kibana的Dev Tools进行测试,然后将其转换为Python Elasticsearch DSL兼容格式,可以更轻松地编写更复杂的内容 - 所以在Kibana中,我最终想出了以下内容:

GET index1/_search
{
  "query": {
    "match_phrase": {
      "name": {
        "query": "john"
      }
    }
  },
  "sort": {
    "_script": {
      "type": "number",
      "script": {
        "lang": "painless",
        "source": "Math.abs(doc['age'].value - params.target_age)",
        "params": {
          "target_age": 46
        }
      },
      "order": "asc"
    }
  }
}

注意使用差异的绝对值将给出最接近任一方向的值(即更年轻或更老)。 如果您的要求不同,可能需要进行一些调整。 只需在查询更改时调整参数,以适应不同的目标年龄。

经过测试和验证后,转换为Python Elasticsearch DSL非常简单 - 您可以使用“自动缩进”功能来平滑sort的复杂性并将其直接放入现有语句中。

s = Search(using=es, index="index1").extra(size=500) \
    .query("match_phrase", name={"query": "john".casefold()}) \
    .sort({"_script":{"type":"number","script":{"lang":"painless","source": \
    "Math.abs(doc['age'].value - params.target_age)", \
    "params":{"target_age":46}},"order":"asc"}})

执行此操作将返回预期的响应:

<Response: [<Hit(index1/_doc/VR3e7WkBsHIsqLp6vfx_): {'name': 'John White', 'age': 46}>, <Hit(index1/_doc/Vx3f7WkBsHIsqLp6DPxM): {'name': 'John Black', 'age': 47}>, <Hit(index1/_doc/Vh3e7WkBsHIsqLp6yfxd): {'name': 'John White', 'age': 40}>]>

但是,如您所示,您想要最接近的值,我建议您将size参数更改为1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM