我有一个看起来像这样的文件:
{
"spans" : [
{
"from" : ISODate("2016-01-01T00:00:00.000+0000"),
"to" : ISODate("2016-01-02T00:00:00.000+0000")
},
{
"from" : ISODate("2016-01-03T00:00:00.000+0000"),
"to" : ISODate("2016-01-04T00:00:00.000+0000")
},
{
"from" : ISODate("2016-02-01T00:00:00.000+0000"),
"to" : ISODate("2016-02-04T00:00:00.000+0000")
}
]
}
我想查询文档,但只返回大于2016-1-2
的跨度我首先尝试了$ elemMatch,但它只返回第一个匹配范围。
似乎$filter运算符是正确的方法,但我似乎无法在ProjectionBuilder上找到任何方法来进行过滤。
我想我想做一个这样的查询:
.aggregate([
{
$match:{/*Some other filter*/}
},
{
$project: {
Spans: {
$filter: {
input: "$spans",
as: "span",
cond: { $gt: [ "$$span.from", ISODate("2016-01-02T00:00:00Z") ] }
}
}
}
}
])
我认为它应该是这样的,但没有过滤方法
var pb = new ProjectionDefinitionBuilder<MyObj>();
var projection = pb.Combine(new List<ProjectionDefinition<MyObj>> {
pb.Filter(x => x.Spans, s => s.From > from))//no such thing...
});
var result= _collection.
.Match(x=>/*my match*/)
.Project<MyObj>(projection)
.ToList();
我错过了什么?它不是我应该使用的ProjectionBuilder吗?
答案 0 :(得分:2)
有两种,可能有更多方法可以解决这个问题。您可以将$project
与$filter
一起使用,也可以使用普通且可靠的$unwind
。
我使用shell查询编写一个示例,并确信您可以轻松转换为C#。
解决方案#1
db.collection.aggregate([
{$unwind:"$spans"},
{$match: {"spans.from": {$gt: ISODate("2016-01-02T00:00:00.000+0000")}}},
{$group:{_id:"$_id", spans:{$push:"$spans"}}}
])
解决方案#2 仅支持MongoDB 3.2+版
db.collection.aggregate([
{$project:
{spans:
{$filter:
{input:"$spans", as: "spans", cond:
{$gt: ["$$spans.from", ISODate("2016-01-02T00:00:00.000+0000")]}
}
}
}
}
])
上面的示例将过滤掉ISODate("2016-01-02T00:00:00.000+0000")
中小于或等于from
的所有数组元素,最终结果如下:
{
"_id" : ObjectId("5804123984d3eb497d538a6e"),
"spans" : [
{
"from" : ISODate("2016-01-03T00:00:00.000+0000"),
"to" : ISODate("2016-01-04T00:00:00.000+0000")
},
{
"from" : ISODate("2016-02-01T00:00:00.000+0000"),
"to" : ISODate("2016-02-04T00:00:00.000+0000")
}
]
}