使用mongo查询日期范围

时间:2014-02-06 20:16:14

标签: mongodb

我的文档如下:

> db.users.find().pretty()
{
        "_id" : ObjectId("52ee0844177c86dc1d000001"),
        "profile" : {
                "displayName" : "Sydney",
        },
        "todos" : [
                {
                        "date" : ISODate("2014-02-02T21:47:13.064Z"),
                        "value" : "#first in the #middle also but twice #middle and the #end",
                        "tags" : [
                                "#first",
                                "#middle",
                                "#end"
                        ]
                },
                {
                        "date" : ISODate("2014-02-05T21:20:30.904Z"),
                        "value" : "Find mongo query #mongo #work",
                        "tags" : [
                                "#mongo",
                                "#work"
                        ]
                }
        ]
}

我想查询待办事项的日期范围:

> var start = new Date()
> var end = new Date()
> start.setDate(start.getDate() - 2)
1391544140700
> start
ISODate("2014-02-04T20:02:20.700Z")
> end
ISODate("2014-02-06T20:02:25.828Z")
>db.users.find({todos: {$elemMatch: {date: { $gte: start, $lt: end }}}}, {'todos':1}).pretty()

但查询仍会返回两条记录。我原以为只能拿到最后一个。

1 个答案:

答案 0 :(得分:2)

来自文档:

  

如果多个元素与$ elemMatch条件匹配,则为运算符   返回数组中第一个匹配元素。

这是设计(限制),并且没有其他运算符只返回匹配的元素。一种方法是使用聚合框架来过滤返回的数组元素:

db.users.aggregate([
    {$match: {todos: {$elemMatch: {date: { $gte: start, $lt: end }} } }},
    {$unwind: "$todos"},
    {$match:{"todos.date": { $gte: start, $lt: end } }},
    {$group: { _id: { _id: "$_id", profile: "$profile" }, todos: {$push: "$todos" } } },
    {$project: {_id: "$_id._id", profile: "$_id.profile", todos: 1 } }
])

如果只需要一个字段,请将positional运算符与$ elemMatch结合使用,仅返回匹配项,因为在投影中重新设置$ elemMatch是没有多大意义的。

{todos: {$elemMatch: {date: { $gte: start, $lt: end }}}}, {"todos.$": 1}