如何使用ElasticSearch无痛脚本查找与先前搜索结果匹配的记录

时间:2019-04-18 08:19:13

标签: elasticsearch elasticsearch-painless

我在下面附加了索引。

索引中的每个文档都包含Alice或Bob的名称和高度以及测量高度的年龄。在10岁时进行的测量被标记为“ baseline_height_at_age_10”:是

我需要执行以下操作:

  1. 找到10岁时爱丽丝和鲍勃的身高。
  2. 列表项返回Alice和Bob的记录,这些记录的身高低于10岁时的身高。

所以我的问题是:可以进行无痛搜索吗? 如果您能为我指出一个很好的例子,我将不胜感激。

也:ElasticSearch无痛甚至是解决此问题的好方法吗?你可以建议

索引映射

PUT /shlomi_test/
{
  "mappings": {
    "_doc": {
      "properties": {
        "first_name": {
          "type": "keyword",
          "fields": {
            "raw": {
              "type": "text"
            }
          }
        },
        "surname": {
          "type": "keyword",
          "fields": {
            "raw": {
              "type": "text"
            }
          }
        },
        "baseline_height_at_age_10": {
          "type": "boolean"
        },
        "age": {
          "type": "integer"
        },
        "height": {
          "type": "integer"
        }
      }
    }
  }
}

索引数据

POST /test/_doc/alice_green_8_110
{
  "first_name": "Alice",
  "surname": "Green",
  "age": 8,
  "height": 110,
  "baseline_height_at_age_10": false
}

POST /test/_doc/alice_green_10_120
{
  "first_name": "Alice",
  "surname": "Green",
  "age": 10,
  "height": 120,
  "baseline_height_at_age_10": true
}

POST /test/_doc/alice_green_13_140
{
  "first_name": "Alice",
  "surname": "Green",
  "age": 13,
  "height": 140,
  "baseline_height_at_age_10": false
}

POST /test/_doc/alice_green_23_170
{
  "first_name": "Alice",
  "surname": "Green",
  "age": 23,
  "height": 170,
  "baseline_height_at_age_10": false
}



POST /test/_doc/bob_green_8_120
{
  "first_name": "Alice",
  "surname": "Green",
  "age": 8,
  "height": 120,
  "baseline_height_at_age_10": false
}

POST /test/_doc/bob_green_10_130
{
  "first_name": "Alice",
  "surname": "Green",
  "age": 10,
  "height": 130,
  "baseline_height_at_age_10": true
}

POST /test/_doc/bob_green_15_160
{
  "first_name": "Alice",
  "surname": "Green",
  "age": 15,
  "height": 160,
  "baseline_height_at_age_10": false
}

POST /test/_doc/bob_green_21_180
{
  "first_name": "Alice",
  "surname": "Green",
  "age": 21,
  "height": 180,
  "baseline_height_at_age_10": false
}

2 个答案:

答案 0 :(得分:1)

您应该仅使用聚合即可做到这一点。假设人们只会越来越高,并且测量结果是准确的,则可以将查询限制为仅年龄在10岁或以下的那些文件,找到那些文件的最大高度,然后过滤那些文件的结果以排除基线结果

POST test/_search
{
  "size": 0,
  "query": {
    "range": {
      "age": {
        "lte": 10
      }
    }
  },
  "aggs": {
    "names": {
      "terms": {
        "field": "first_name",
        "size": 10
      },
      "aggs": {
        "max_height": {
          "max": {
            "field": "height"
          }
        },
        "non-baseline": {
          "filter": {
            "match": {
              "baseline_height_at_age_10": false
            }
          },
          "aggs": {
            "top_hits": {
              "top_hits": {
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}

答案 1 :(得分:1)

我已经发布了相同的问题,重点是无痛脚本编写,ElasticSearch支持论坛How to find records matching the result of a previous search using ElasticSearch Painless scripting

答案是:

  

“我认为无痛方法在这里不会奏效。您不能使用   一个查询的结果以使用Painless执行第二个查询。

     

您在文章末尾概述的两步方法是   要走的路。”

最重要的是,您不能将一个查询的结果用作另一查询的输入。您可以过滤和聚合更多,但不能这样做。

因此,方法大致如下:

  

根据我的理解,建议进行第一次搜索,处理   数据并进行其他搜索。这基本上转化为:

  1. 搜索记录,其中first_name = Alice,baseline_height_at_age_10 = True。
  2. 从外部进行处理,以提取10岁时爱丽丝的身高值。
  3. 搜索Alice的身高低于外部计算值的记录。