【问题标题】:Nest Elastic - Building Dynamic Nested QueryNest Elastic - 构建动态嵌套查询
【发布时间】:2016-04-02 11:27:15
【问题描述】:

我必须使用 Nest 查询嵌套对象,但是查询是以动态方式构建的。下面是演示以静态方式对嵌套“书籍”使用查询的代码

QueryContainer qry;
         qry = new QueryStringQuery()
         {
             DefaultField = "name",
             DefaultOperator = Operator.And,
             Query = "salman"
         };

         QueryContainer qry1 = null;

         qry1 = new RangeQuery() // used to search for range ( from , to)
         {
             Field = "modified",
             GreaterThanOrEqualTo = Convert.ToDateTime("21/12/2015").ToString("dd/MM/yyyy"),
         };

         QueryContainer all = qry && qry1;

            var results = elastic.Search<Document>(s => s
               .Query(q => q
                    .Bool(qb => qb
                        .Must(all)))
                .Filter(f =>
                        f.Nested(n => n
                             .Path("books")
                                .Filter(f3 => f3.And(
                                            f1 => f1.Term("book.isbn", "122"),
                                            f2 => f2.Term("book.author", "X"))

                                        )
                                )
                        )   

                );

问题是我需要以动态方式为“书籍”组合多个查询(使用 And、OR 运算符)。例如,获取满足这些条件的书籍:

  1. 条件 1:作者为“X”且 isbn 为“1”的图书
  2. 条件 2:作者为“X”且 isbn 为“2”的图书
  3. 条件 3:作者为“Z”且 isbn 为“3”的图书
  4. 其他条件:.....

现在,嵌套查询中的过滤器应该检索书籍,如果:
条件 1 AND 条件 2 条件 3

假设我的类名 FilterOptions 包含以下属性:

  1. 字段名称
  2. 价值
  3. 运算符(将组合下一个过滤器)

我将在给定的 FilterOptions 数组上循环以构建查询。

问题:

我应该使用什么来构建嵌套查询?它是一个 FilterDescriptor 以及如何将它们组合起来将嵌套查询添加到搜索方法中?

请推荐任何有价值的链接或示例?

【问题讨论】:

    标签: dynamic elasticsearch nested nest booleanquery


    【解决方案1】:

    我同意 paeloque,您的前两个条件似乎是矛盾的,如果 AND-ed 一起使用,则不会起作用。忽略这一点,这是我的解决方案。我已经以允许超过您拥有的三个特定条件的方式实现了这一点。我也觉得它更适合 bool 声明。

    QueryContainer andQuery = null;
    QueryContainer orQuery = null;
    foreach(var authorFilter in FilterOptions.Where(f=>f.Operator==Operator.And))
    {
        andQuery &= new TermQuery
        {
            Field = authorFilter.FieldName,
            Value = authorFilter.Value
        };
    }
    foreach(var authorFilter in FilterOptions.Where(f=>f.Operator==Operator.Or))
    {
        orQuery |= new TermQuery
        {
            Field = authorFilter.FieldName,
            Value = authorFilter.Value
        };
    }
    

    在那之后,我会在.Nested 电话中输入:

    .Path("books")
        .Query(q=>q
            .Bool(bq=>bq
                .Must(m=>m.MatchAll() && andQuery)
                .Should(orQuery)
        ))
    

    【讨论】:

    • 我一直在寻找这个答案,两天后......谢谢......节省了我的一天
    【解决方案2】:

    Condition 1Condition 2 的特定情况下,您可能不会得到任何结果,因为这些是排他性条件。但我现在假设,您希望获得与这些条件中的任何一个匹配的结果。您选择了嵌套,这绝对是要走的路。使用嵌套类型,您可以将参数组合为一本书。

    组合嵌套查询

    对于您的用例,我将使用带有 mustshould 子句的 bool 查询类型。 获取 Condition 1Condition 2 书籍的查询将是:

    POST /books/_search
    {
       "query": {
          "bool": {
             "should": [
                {
                   "nested": {
                      "path": "books",
                      "query": {
                         "bool": {
                            "must": [
                               {
                                  "match": {
                                     "books.isbn": "2"
                                  }
                               },
                               {
                                  "match": {
                                     "books.author": "X"
                                  }
                               }
                            ]
                         }
                      }
                   }
                },
                {
                   "nested": {
                      "path": "books",
                      "query": {
                         "bool": {
                            "must": [
                               {
                                  "match": {
                                     "books.isbn": "1"
                                  }
                               },
                               {
                                  "match": {
                                     "books.author": "X"
                                  }
                               }
                            ]
                         }
                      }
                   }
                }
             ]
          }
       }
    }
    

    你能解释一下,为什么你的书是嵌套的?无需将它们嵌套在顶级结构中,而是直接作为索引/类型中的顶级对象进行索引,您可以简化查询。

    未分析

    还有一个需要提醒的注意事项:如果您希望作者和 ISBN 完全匹配,您必须确保将 ISBN 和作者字段设置为 not_analyzed。否则他们会被分析并分成几部分,你的匹配就不会很好。

    例如如果你有一个带破折号的 ISBN 号码,那么它将被分成几部分:

    978-3-16-148410-0
    

    将被索引为:

    978
    3
    16
    148410
    0
    

    使用完全相同的 ISBN 编号进行搜索会为您提供所有在其 ISBN 编号中具有子编号之一的书籍。如果要防止这种情况,请使用not_analyzed 索引类型和Multi-fields

      "isbn": {
         "type": "string",
         "fields": {
            "raw": {
               "type": "string",
               "index": "not_analyzed"
            }
         }
      }
    

    然后要解决not_analyzed isbn 字段,您必须调用它:

    books.isbn.raw
    

    希望这会有所帮助。

    【讨论】:

    • 实际上,当查询不满足预期的结果时,我进入了嵌套对象,即在书籍上执行这两个条件。此链接将澄清我的问题:[stackoverflow.com/questions/34400601/…
    • 如何使用 NEST 构建此查询?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多