【问题标题】:elastic search: how to terminate a multi search query once we get desired result弹性搜索:一旦我们得到想要的结果,如何终止多搜索查询
【发布时间】:2018-12-13 00:51:44
【问题描述】:

我们有一个弹性搜索文档,其中包含一个名为“Type”的字符串字段。该字段可以具有从“A”到“Z”的不同值。多个文档可以具有相同的类型,即多个文档可以具有类型“A”

我们想编写一个弹性搜索查询,最多返回 30 个这样的文档。我们希望输出根据类型在不同的组中。例如:

  1. 如果我们有 10 个 A 类文档,15 个 B 类文档,20 个 C 类文档,我应该得到所有 10 个 A 类文档,所有 15 个 B 类文档和 5 个 C 类文档。
  2. 如果我们有 0 个 A 类文档、10 个 B 类文档、15 个 C 类文档、20 个 D 类文档,我应该得到所有 10 个 B 类文档、15 个 C 类文档和 5 个 D 类文档。
  3. 最坏的情况:如果我们没有任何 A ... Y 类型的文档和 30 个 Z 类型的文档,我应该得到 30 个 Z 类型的文档。

我为此编写了一个非常基本的多搜索查询(总共 26 个查询),即

    POST _msearch/
    {"index":"<index_name>","type":"<type>"}
    {"from":0,"size":30,"query":{"bool":{"must":[{"terms":{"type":["A"]}}]}}}
    {"index":"<index_name>","type":"<type>"}
    {"from":0,"size":30,"query":{"bool":{"must":[{"terms":{"type":["B"]}}]}}}
    ...
    {"index":"<index_name>","type":"<type>"}
    {"from":0,"size":30,"query":{"bool":{"must":[{"terms":{"type":["Z"]}}]}}}

我担心多搜索查询的执行,即对于案例 1 和案例 2,我们得到了足够的输出,即前几个查询的 30 个文档,那么我们为什么要执行其余的多搜索查询呢?一旦我们获得所需数量的结果,是否有任何方法可以停止多搜索查询操作,即一旦我们获得 30 个或更多结果就终止多搜索。

请注意:

  1. 我在这里给出了非常简单的条件,即不同的多重搜索的条件比仅仅基于类型更复杂。
  2. 我们希望输出中有多个集合,即 A 类、B 类等都在不同的集合中。 (由于这个限制,我们不得不排除无痛脚本选项)

【问题讨论】:

    标签: elasticsearch elasticsearch-5 elasticsearch-painless


    【解决方案1】:

    看起来您可以通过使用sizesort 进行一次搜索来实现您想要的结果,还可以选择使用bool 将查询组合为一个。

    我可以提前终止多搜索查询吗?

    没有。从Multi Search 的文档中我们可以得出结论。它以一定的并发性执行多个搜索请求,并仅在所有查询完成后才发回结果。

    它很像Bulk API,一种轻松执行并行请求的方法。

    我可以按自定义顺序获取匹配的文档吗?

    是的,这就是sort 的用途。为了实现原始帖子中描述的行为,使用这个调用就足够了:

    POST /<index_name>/<index_type>/_search?sort=type:asc&size=30
    

    我可以在多个索引上发出一个搜索请求并仍然使用sort吗?

    是的,你只需要定义索引列表:

    POST /multisearch1,mutlisearch2/<index_type>/_search?sort=type:asc&size=30
    

    或通配符表达式:

    POST /multisearch*/<index_type>/_search?sort=type:asc&size=30
    

    我可以按任意顺序排序吗?

    是的,例如使用Script Based Sorting。例如,如果您希望按以下顺序在结果中看到typeXCA,您可以编写如下脚本:

    POST /<index_name>/<type>/_search
    {
      "size": 30,
      "sort": {
        "_script": {
          "type": "number",
          "script": {
            "lang": "painless",
            "source": """
    int r = 1;
    if(doc['type'].value  == 'X') { 
      r = 100;
    } else if(doc['type'].value  == 'C') { 
      r = 10;
    } else if(doc['type'].value  == 'A') { 
      r = 5;
    }
      r;
    """
          },
          "order": "desc"
        }
      }
    }
    

    这也适用于多个集合(如上面的查询)。

    如果我有一个依赖于type 值的复杂查询,我可以这样做吗?

    是的,没问题,以bool查询为例:

    POST /<index_name>/<type>/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "bool": {
                "must": [
                  {
                    "term": {
                      "type": "A"
                    }
                  },
                  {
                    "match": {
                      "description": "Quick fox"
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "must": [
                  {
                    "term": {
                      "type": "X"
                    }
                  },
                  {
                    "match": {
                      "description": "Quick bear"
                    }
                  }
                ]
              }
            }
          ]
        }
      },
      "size": 30,
      "sort": {
        "_script": {
          "type": "number",
          "script": {
            "lang": "painless",
            "source": """
    int r = 1;
    if(doc['type'].value  == 'X') { 
      r = 100;
    } else if(doc['type'].value  == 'C') { 
      r = 10;
    } else if(doc['type'].value  == 'A') { 
      r = 5;
    }
      r;
    """
          },
          "order": "desc"
        }
      }
    }
    

    希望有帮助!

    【讨论】:

      猜你喜欢
      • 2019-10-15
      • 1970-01-01
      • 1970-01-01
      • 2015-09-11
      • 1970-01-01
      • 1970-01-01
      • 2021-02-10
      • 1970-01-01
      • 2023-03-09
      相关资源
      最近更新 更多