具有多个术语的 NEST 条件过滤器查询
NEST Conditional filter query with multiple terms
我想像这样进行 ElasticSearch 查询:
{
"query" :
{
"bool" :
{
"filter" : [
{
"terms" :
{
"name" : ["name1", "name2"]
}
},
{
"terms" :
{
"color" : ["orange", "red"]
}
}
]
}
}
}
我试过像这样在 NEST 中实现它:
_elasticClient
.SearchAsync<MyDocument>(s =>
s.Index("myindex")
.Query(q => q
.Bool(bq => bq
.Filter(fq =>
{
QueryContainer query = null;
if (nameList.Any()) {
query &= fq.Terms(t => t.Field(f => f.Name).Terms(nameList));
}
if (colorList.Any()) {
query &= fq.Terms(t => t.Field(f => f.Color).Terms(colorList));
}
return query;
})
)
)
);
但这给了我一个这样的查询,其中过滤器被包裹在 bool must:
中
{
"query" :
{
"bool" :
{
"filter" : [
{
"bool" :
{
"must" : [
{
"terms" :
{
"name" : ["name1", "name2"]
}
},
{
"terms" :
{
"color" : ["orange", "red"]
}
}
]
}
}
]
}
}
}
我应该如何更改我的 NEST 代码以提供正确的查询?必须将我的条款添加到 QueryContainer 以外的其他内容吗?
如果要检查条件过滤器,可以在进行查询之前创建过滤器列表,如下所示:
var nameList = new[] {"a", "b"};
var colorList = new[] {1, 2};
var filters = new List<Func<QueryContainerDescriptor<MyDocument>, QueryContainer>>();
if (nameList.Any())
{
filters.Add(fq=> fq.Terms(t => t.Field(f => f.Name).Terms(nameList)));
}
if (colorList.Any())
{
filters.Add(fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList)));
}
ISearchResponse<Property> searchResponse =
elasticClient.Search<MyDocument>(x => x.Query(q => q
.Bool(bq => bq.Filter(filters))));
如果您在进行过滤器查询之前不需要检查任何条件,那么您可以使用类似的东西:
ISearchResponse<MyDocument> searchResponse =
elasticClient.Search<MyDocument>(x => x.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
))));
bool 查询的 Filter
方法采用 params Func<QueryContainerDescriptor<T>, QueryContainer>[]
以便您可以将多个表达式传递给它来表示多个过滤器
var nameList = new string[] { "name1", "name2" };
var colorList = new string[] { "orange", "red" };
client.SearchAsync<MyDocument>(s => s
.Index("myindex")
.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
)
)
)
);
结果是
{
"query": {
"bool": {
"filter": [
{
"terms": {
"name": [
"name1",
"name2"
]
}
},
{
"terms": {
"color": [
"orange",
"red"
]
}
}
]
}
}
}
NEST also has the concept of conditionless queries,即如果一个查询被确定为无条件的,那么它将不序列化为请求的一部分。
无条件是什么意思?好吧,这取决于查询;例如,在 terms
查询的情况下,如果以下任何一项为真,则认为它是无条件的
field
没有值
- 术语值列表是
null
- 条款值是一个空集合
- 术语值列表有值,但它们都是
null
或空字符串
演示
var emptyNames = new string[] {};
string[] nullColors = null;
client.SearchAsync<MyDocument>(s =>
s.Index("myindex")
.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Name).Terms(emptyNames)),
fq => fq.Terms(t => t.Field(f => f.Color).Terms(nullColors)))
)
)
);
结果
{}
无条件查询有助于更轻松地编写 NEST 查询,因为您无需在构造查询之前检查集合是否具有值。您可以在每个查询的基础上更改无条件语义 using .Strict()
and .Verbatim()
。
var searchResponse = client.Search<EventData>(s => s
.From(0)
.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Client.Id).Terms(17)),
fq => fq.Terms(t => t.Field(f => f.Item.Id).Terms(**new[] { 34983, 35430, 35339, 35300 }**)),
fq => fq.Terms(t=>t.Field(f=>f.Event).Terms("Control de Panico")),
fq => fq.DateRange(dr => dr.Field(f => f.DateTime)
.GreaterThanOrEquals(new DateTime(2018, 07, 01))
.LessThanOrEquals(new DateTime(2018, 10, 02)))
)
))
.Size(2000)
.Sort(g => sortDescriptor)
);
我想像这样进行 ElasticSearch 查询:
{
"query" :
{
"bool" :
{
"filter" : [
{
"terms" :
{
"name" : ["name1", "name2"]
}
},
{
"terms" :
{
"color" : ["orange", "red"]
}
}
]
}
}
}
我试过像这样在 NEST 中实现它:
_elasticClient
.SearchAsync<MyDocument>(s =>
s.Index("myindex")
.Query(q => q
.Bool(bq => bq
.Filter(fq =>
{
QueryContainer query = null;
if (nameList.Any()) {
query &= fq.Terms(t => t.Field(f => f.Name).Terms(nameList));
}
if (colorList.Any()) {
query &= fq.Terms(t => t.Field(f => f.Color).Terms(colorList));
}
return query;
})
)
)
);
但这给了我一个这样的查询,其中过滤器被包裹在 bool must:
中{
"query" :
{
"bool" :
{
"filter" : [
{
"bool" :
{
"must" : [
{
"terms" :
{
"name" : ["name1", "name2"]
}
},
{
"terms" :
{
"color" : ["orange", "red"]
}
}
]
}
}
]
}
}
}
我应该如何更改我的 NEST 代码以提供正确的查询?必须将我的条款添加到 QueryContainer 以外的其他内容吗?
如果要检查条件过滤器,可以在进行查询之前创建过滤器列表,如下所示:
var nameList = new[] {"a", "b"};
var colorList = new[] {1, 2};
var filters = new List<Func<QueryContainerDescriptor<MyDocument>, QueryContainer>>();
if (nameList.Any())
{
filters.Add(fq=> fq.Terms(t => t.Field(f => f.Name).Terms(nameList)));
}
if (colorList.Any())
{
filters.Add(fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList)));
}
ISearchResponse<Property> searchResponse =
elasticClient.Search<MyDocument>(x => x.Query(q => q
.Bool(bq => bq.Filter(filters))));
如果您在进行过滤器查询之前不需要检查任何条件,那么您可以使用类似的东西:
ISearchResponse<MyDocument> searchResponse =
elasticClient.Search<MyDocument>(x => x.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
))));
bool 查询的 Filter
方法采用 params Func<QueryContainerDescriptor<T>, QueryContainer>[]
以便您可以将多个表达式传递给它来表示多个过滤器
var nameList = new string[] { "name1", "name2" };
var colorList = new string[] { "orange", "red" };
client.SearchAsync<MyDocument>(s => s
.Index("myindex")
.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
)
)
)
);
结果是
{
"query": {
"bool": {
"filter": [
{
"terms": {
"name": [
"name1",
"name2"
]
}
},
{
"terms": {
"color": [
"orange",
"red"
]
}
}
]
}
}
}
NEST also has the concept of conditionless queries,即如果一个查询被确定为无条件的,那么它将不序列化为请求的一部分。
无条件是什么意思?好吧,这取决于查询;例如,在 terms
查询的情况下,如果以下任何一项为真,则认为它是无条件的
field
没有值- 术语值列表是
null
- 条款值是一个空集合
- 术语值列表有值,但它们都是
null
或空字符串
演示
var emptyNames = new string[] {};
string[] nullColors = null;
client.SearchAsync<MyDocument>(s =>
s.Index("myindex")
.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Name).Terms(emptyNames)),
fq => fq.Terms(t => t.Field(f => f.Color).Terms(nullColors)))
)
)
);
结果
{}
无条件查询有助于更轻松地编写 NEST 查询,因为您无需在构造查询之前检查集合是否具有值。您可以在每个查询的基础上更改无条件语义 using .Strict()
and .Verbatim()
。
var searchResponse = client.Search<EventData>(s => s
.From(0)
.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Client.Id).Terms(17)),
fq => fq.Terms(t => t.Field(f => f.Item.Id).Terms(**new[] { 34983, 35430, 35339, 35300 }**)),
fq => fq.Terms(t=>t.Field(f=>f.Event).Terms("Control de Panico")),
fq => fq.DateRange(dr => dr.Field(f => f.DateTime)
.GreaterThanOrEquals(new DateTime(2018, 07, 01))
.LessThanOrEquals(new DateTime(2018, 10, 02)))
)
))
.Size(2000)
.Sort(g => sortDescriptor)
);