Mongodb查询子文档中与条件匹配的元素

时间:2016-10-16 23:36:31

标签: c# mongodb

我有一个看起来像这样的文件:

{ 
    "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吗?

1 个答案:

答案 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")
        }
    ]
}