【问题标题】:How to use ElasticSearch Query params (DSL query) for multiple types?如何为多种类型使用 ElasticSearch 查询参数(DSL 查询)?
【发布时间】:2015-07-16 12:10:35
【问题描述】:

过去几个月我一直在使用 ElasticSearch,但是当我必须传递一个复杂的查询时仍然觉得它很复杂。

我想运行必须搜索多个“类型”的查询,并且每种类型都必须使用自己的“过滤器”进行搜索,但需要组合“搜索结果”

例如:

我需要搜索我的朋友的“用户类型”文档,同时我必须根据提供的关键字搜索我喜欢的“对象类型”文档。

同时包含“AND”和“NOT”子句的查询

查询示例:

$options['query'] = array(
        'query' => array(
            'filtered' => array(
                'query' => array(
                    'query_string' => array(
                        'default_field' => 'name',
                        'query' => $this->search_term . '*',
                    ),
                ),
                'filter' => array(
                    'and' => array(
                        array(
                            'term' => array(
                                'access_id' => 2,
                            ),
                        ),
                    ),

                    'not' => array(
                        array(
                            'term' => array(
                                'follower' => 32,
                            ),
                        ),

                        array(
                            'term' => array(
                                'fan' => 36,
                            ),
                        ),
                    ),
                ),
            ),
        ),
    );

因为这个查询是为了搜索access_id = 2的用户,但不能有id 32的follower和id 36的fan

但这不起作用..

编辑:修改后的查询

{
  "query": {
    "filtered": {
      "filter": {
        "and": [
          {
            "not": {
              "filter": {
                "and": [
                  {
                    "query": {
                      "query_string": {
                        "default_field": "fan",
                        "query": "*510*"
                      }
                    }
                  },
                  {
                    "query": {
                      "query_string": {
                        "default_field": "follower",
                        "query": "*510*"
                      }
                    }
                  }
                ]
              }
            }
          },
          {
            "term": {
              "access_id": 2
            }
          }
        ]
      },
      "query": {
        "field": {
          "name": "xyz*"
        }
      }
    }
  }
}

现在运行此查询后,我得到两个结果,一个是关注者:“34,518”和粉丝:“510”,第二个是粉丝:“34”,但它不应该只是结果中的第二个。

有什么想法吗?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    您可能想查看我本月提供的演示文稿的幻灯片,其中解释了查询 DSL 工作原理的基础知识:

    Terms of endearment - the ElasticSearch Query DSL explained

    您的查询的问题是您的过滤器嵌套不正确。 andnot 过滤器处于同一级别,但 not 过滤器应位于 and 之下:

    curl -XGET 'http://127.0.0.1:9200/_all/_search?pretty=1'  -d '
    {
       "query" : {
          "filtered" : {
             "filter" : {
                "and" : [
                   {
                      "not" : {
                         "filter" : {
                            "and" : [
                               {
                                  "term" : {
                                     "fan" : 36
                                  }
                               },
                               {
                                  "term" : {
                                     "follower" : 32
                                  }
                               }
                            ]
                         }
                      }
                   },
                   {
                      "term" : {
                         "access_id" : 2
                      }
                   }
                ]
             },
             "query" : {
                "field" : {
                   "name" : "keywords to search"
                }
             }
          }
       }
    }
    '
    

    【讨论】:

    • “not”过滤器是否总是在“and”过滤器之下,或者只是在这种情况下
    • 您编辑的问题引入了其他问题。我建议您查看我链接到的演示文稿 - 它解释了术语和文本之间的区别,以及在哪里使用哪些类型的查询或过滤器。
    • 嗯,我一直在研究您的幻灯片并对其进行了大量实验。同时,您能否告诉我stackoverflow.com/questions/7194823/… 是否好用,或者我应该只使用文件管理器。谢谢你的时间。
    • 你有这个演示文稿的录音吗?
    • 很遗憾,它现在已经很老了。关注 elasticsearch.org,《权威指南》这本书的第一部分将在下个月左右上线,应该会有很大帮助。
    【解决方案2】:

    我刚刚用“BOOL”试了一下

    {
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "access_id": 2
              }
            },
            {
              "wildcard": {
                "name": "xyz*"
              }
            }
          ],
          "must_not": [
            {
              "wildcard": {
                "follower": "*510*"
              }
            },
            {
              "wildcard": {
                "fan": "*510*"
              }
            }
          ]
        }
      }
    }
    

    它给出了正确的答案。

    但我不确定它应该这样使用吗?

    【讨论】:

    • 这可行,但效率极低。通配符子句必须加载所有术语,找到所有匹配的术语,然后重写查询以包含所有这些术语。那真的可以炸了。最好在索引时正确分析您的数据,这样您就可以将您的值分解为单独的术语,您可以单独匹配这些术语。您可能需要考虑使用 ngram 分析器,但这实际上取决于您的数据。看看这个线程的例子elasticsearch-users.115913.n3.nabble.com/…
    • 感谢@DrTech,解释得很好。 +1。我真的想说你应该写一篇关于 ElasticSearch 的完整教程,因为还没有人做过 :) 谢谢
    • 关于如何将“范围”查询与“匹配”混合的任何线索。我觉得应该有数百个这样的例子,但文档中什么都没有?
    猜你喜欢
    • 1970-01-01
    • 2021-05-21
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多