Nest Elastic - 构建动态嵌套查询

时间:2015-12-28 15:45:49

标签: dynamic elasticsearch nested nest booleanquery

我必须使用Nest查询嵌套对象,但查询是以动态方式构建的。下面的代码演示了如何在嵌套" books"上使用查询。以静态的方式

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运算符)组合成&#34; books&#34;以动态的方式。例如,获取满足这些条件的书籍:

  1. 条件1:拥有作者&#34; X&#34;和isbn&#34; 1&#34;
  2. 条件2:拥有作者&#34; X&#34;和isbn&#34; 2&#34;
  3. 条件3:有作者&#34; Z&#34;和isbn&#34; 3&#34;
  4. 其他条件:.....
  5. 现在,嵌套查询中的过滤器应该在以下情况下检索书籍:
    条件1 AND 条件2 条件3

    假设我有类名FilterOptions,它包含以下属性:

    1. 字段名
    2. 运算符(将结合下一个过滤器)
    3. 我将循环使用给定的FilterOptions数组来构建查询。

        

      问题:

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

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

2 个答案:

答案 0 :(得分:11)

我同意paweloque,看来你的前两个条件是相互矛盾的,如果和它们在一起就行不通。忽略这一点,这是我的解决方案。我已经实现了这种方式,允许超过你拥有的三个特定条件。我也觉得它在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)
    ))

答案 1 :(得分:1)

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

合并嵌套查询

对于您的用例,我会使用boolmust条款的should查询类型。 获取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。否则,他们会被分析并分成几部分,你的匹配将无法正常工作。

E.g。如果你有一个带破折号的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

希望这有帮助。