我正在将Elasticsearch 5.2与Nest客户端一起使用进行查询。我有一个有效的查询,日期范围如下:
var boolQuery = new BoolQueryDescriptor<AttractionDocument>();
//https://github.com/elastic/elasticsearch-net/issues/2570 must is not additive, we cannot split out query as before it all has to be one big one
boolQuery.Must(
mn => AddRegionQuery(permissions, mn),
mn => AddOffersQuery(permissions, mn),
mn => request.AddDateFilter ? mn.DateRange(d => d.Field(f => f.AvailableFrom).LessThanOrEquals(DateTime.Now)) : mn,
mn => request.AddDateFilter ? mn.DateRange(d => d.Field(f => f.AvailableTo).GreaterThanOrEquals(DateTime.Now)) : mn,
mn => AddGenresQuery(genres, mn)
);
我遇到的问题Availableava并不总是填充,因此对于某些文档来说将不存在。
我尝试添加以下内容:
if (request.AddDateFilter)
{
boolQuery.MustNot(mn => mn.Exists(f => f.Field(e => e.AvailableTo)));
}
现在的问题是查询变得过于严格。理想情况下,我应该作为存在的一部分?我要达到的目标是,如果我们具有该字段,则仅对AvailableTo应用日期范围,否则忽略并返回没有该日期的结果。如果我删除了AvailableTo部分,我会得到结果。
答案 0 :(得分:2)
您应该能够将exists
查询与range
上的AvailableTo
查询合并,以包含AvailableTo
字段存在且必须满足范围条件的文档,并在AvailableTo
查询bool
子句中与must_not
存在查询创建分词,即反转存在。
类似于以下内容(我已注释掉未提供的查询)
var client = new ElasticClient(settings);
var request = new
{
AddDateFilter = true
};
var boolQuery = new BoolQueryDescriptor<AttractionDocument>();
boolQuery.Must(
// mn => AddRegionQuery(permissions, mn),
// mn => AddOffersQuery(permissions, mn),
mn => request.AddDateFilter ? mn.DateRange(d => d.Field(f => f.AvailableFrom).LessThanOrEquals(DateTime.Now)) : mn,
mn => request.AddDateFilter ? (mn.Exists(d => d.Field(f => f.AvailableTo)) &&
mn.DateRange(d => d.Field(f => f.AvailableTo).GreaterThanOrEquals(DateTime.Now))) ||
!mn.Exists(d => d.Field(f => f.AvailableTo)) : mn //,
// mn => AddGenresQuery(genres, mn)
);
client.Search<AttractionDocument>(s => s
.Query(q => q.Bool(b => boolQuery))
);
这将产生以下查询
{
"query": {
"bool": {
"must": [
{
"range": {
"availableFrom": {
"lte": "2018-11-15T20:18:10.528482+10:00"
}
}
},
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"exists": {
"field": "availableTo"
}
},
{
"range": {
"availableTo": {
"gte": "2018-11-15T20:18:10.5304815+10:00"
}
}
}
]
}
},
{
"bool": {
"must_not": [
{
"exists": {
"field": "availableTo"
}
}
]
}
}
]
}
}
]
}
}
}
由于范围查询和存在查询是谓词(文档匹配条件或不匹配),而不是应该计算相关性得分的查询,因此这些查询可能是bool
查询filter
子句< / p>
boolQuery.Must(
// Uncomment below queries, or add (QueryContainer[])null to run
// mn => AddRegionQuery(permissions, mn),
// mn => AddOffersQuery(permissions, mn),
// mn => AddGenresQuery(genres, mn)
).Filter(
mn => request.AddDateFilter ? mn.DateRange(d => d.Field(f => f.AvailableFrom).LessThanOrEquals(DateTime.Now)) : mn,
mn => request.AddDateFilter ? (+mn.Exists(d => d.Field(f => f.AvailableTo)) &&
+mn.DateRange(d => d.Field(f => f.AvailableTo).GreaterThanOrEquals(DateTime.Now))) ||
!mn.Exists(d => d.Field(f => f.AvailableTo)) : mn
);
client.Search<AttractionDocument>(s => s
.Query(q => q.Bool(b => boolQuery))
);
创建查询
{
"query": {
"bool": {
"filter": [
{
"range": {
"availableFrom": {
"lte": "2018-11-15T20:22:25.4556963+10:00"
}
}
},
{
"bool": {
"should": [
{
"bool": {
"filter": [
{
"exists": {
"field": "availableTo"
}
},
{
"range": {
"availableTo": {
"gte": "2018-11-15T20:22:25.4587138+10:00"
}
}
}
]
}
},
{
"bool": {
"must_not": [
{
"exists": {
"field": "availableTo"
}
}
]
}
}
]
}
}
]
}
}
}
Operator overloading on queries在这里确实有帮助,可以更简洁地编写复杂的布尔查询
答案 1 :(得分:0)
好吧,以为我对此感到怀疑。我取出了必须的日期范围,并将其设为应有的日期,因此现在查询如下:
var boolQuery = new BoolQueryDescriptor<AttractionDocument>();
if (request.AddDateFilter)
{
boolQuery.Should(mn => mn.DateRange(d => d.Field(f => f.AvailableTo).GreaterThanOrEquals(DateTime.Now)));
}
//https://github.com/elastic/elasticsearch-net/issues/2570 must is not additive, we cannot split out query as before it all has to be one big one
boolQuery.Must(
mn => AddRegionQuery(permissions, mn),
mn => AddOffersQuery(permissions, mn),
mn => request.AddDateFilter ? mn.DateRange(d => d.Field(f => f.AvailableFrom).LessThanOrEquals(DateTime.Now)) : mn,
mn => AddGenresQuery(genres, mn)
);
我现在返回日期和匹配范围内未设置availableTo日期的结果。