Nest Elastic - 构建动态嵌套查询
Nest Elastic - Building Dynamic Nested Query
我必须使用 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"))
)
)
)
);
问题是我需要以动态方式组合 "books" 的多个查询(使用 And、OR 运算符)。例如,获取满足这组条件的书籍:
- 条件 1:作者为 "X" 且 isbn 为“1”的图书
- 条件 2:作者为 "X" 且 isbn 为“2”的图书
- 条件 3:作者为 "Z" 且 isbn 为“3”的图书
- 其他条件:.....
现在,嵌套查询中的过滤器应该检索书籍,如果:
条件 1 AND 条件 2 Or 条件 3
假设我有 class 包含以下属性的名称 FilterOptions:
- 字段名
- 价值
- 运算符(将结合下一个过滤器)
我将在给定的 FilterOptions 数组上循环以构建查询。
Question:
我应该使用什么来构建嵌套查询?它是 FilterDesciptor 以及如何组合它们将嵌套查询添加到搜索方法?
请推荐任何有价值的link或示例?
在 Condition 1
和 Condition 2
的特定情况下,您可能不会得到任何结果,因为这些是排他性条件。但我现在假设,您希望获得符合这些条件之一的结果。您选择了嵌套,这绝对是正确的选择。使用嵌套类型,您可以为一本书组合参数。
组合嵌套查询
对于您的用例,我将使用带有 must
或 should
子句的 bool
查询类型。
获取 Condition 1
或 Condition 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"
}
}
]
}
}
}
}
]
}
}
}
你能解释一下,为什么你的书是嵌套的?无需将它们嵌套在顶级结构中,而是直接作为 index/type 中的顶级对象进行索引,您可以简化查询。
Not-Analyzed
还有一点需要提醒您:如果您希望作者和 ISBN 完全匹配,您必须确保 ISBN 和作者字段设置为 not_analyzed
。否则他们会被分析并分成几部分,你的比赛就不会很好地进行。
例如如果您有带破折号的 ISBN 编号,那么它会被分成几部分:
978-3-16-148410-0
将被索引为:
978
3
16
148410
0
使用完全相同的 ISBN 编号进行搜索会为您提供 ISBN 编号中包含 sub-numbers 之一的所有图书。如果你想防止这种情况,使用 not_analyzed
index-type 和 Multi-fields:
"isbn": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
然后要解决 not_analyzed
isbn 字段,您必须调用它:
books.isbn.raw
希望这对您有所帮助。
我同意 paweloque 的观点,看来你的前两个条件是矛盾的,如果 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)
))
我必须使用 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"))
)
)
)
);
问题是我需要以动态方式组合 "books" 的多个查询(使用 And、OR 运算符)。例如,获取满足这组条件的书籍:
- 条件 1:作者为 "X" 且 isbn 为“1”的图书
- 条件 2:作者为 "X" 且 isbn 为“2”的图书
- 条件 3:作者为 "Z" 且 isbn 为“3”的图书
- 其他条件:.....
现在,嵌套查询中的过滤器应该检索书籍,如果:
条件 1 AND 条件 2 Or 条件 3
假设我有 class 包含以下属性的名称 FilterOptions:
- 字段名
- 价值
- 运算符(将结合下一个过滤器)
我将在给定的 FilterOptions 数组上循环以构建查询。
Question:
我应该使用什么来构建嵌套查询?它是 FilterDesciptor 以及如何组合它们将嵌套查询添加到搜索方法?
请推荐任何有价值的link或示例?
在 Condition 1
和 Condition 2
的特定情况下,您可能不会得到任何结果,因为这些是排他性条件。但我现在假设,您希望获得符合这些条件之一的结果。您选择了嵌套,这绝对是正确的选择。使用嵌套类型,您可以为一本书组合参数。
组合嵌套查询
对于您的用例,我将使用带有 must
或 should
子句的 bool
查询类型。
获取 Condition 1
或 Condition 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"
}
}
]
}
}
}
}
]
}
}
}
你能解释一下,为什么你的书是嵌套的?无需将它们嵌套在顶级结构中,而是直接作为 index/type 中的顶级对象进行索引,您可以简化查询。
Not-Analyzed
还有一点需要提醒您:如果您希望作者和 ISBN 完全匹配,您必须确保 ISBN 和作者字段设置为 not_analyzed
。否则他们会被分析并分成几部分,你的比赛就不会很好地进行。
例如如果您有带破折号的 ISBN 编号,那么它会被分成几部分:
978-3-16-148410-0
将被索引为:
978
3
16
148410
0
使用完全相同的 ISBN 编号进行搜索会为您提供 ISBN 编号中包含 sub-numbers 之一的所有图书。如果你想防止这种情况,使用 not_analyzed
index-type 和 Multi-fields:
"isbn": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
然后要解决 not_analyzed
isbn 字段,您必须调用它:
books.isbn.raw
希望这对您有所帮助。
我同意 paweloque 的观点,看来你的前两个条件是矛盾的,如果 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)
))