mongoose 4.7.5:如何获取数组中的子文档

时间:2017-03-12 13:19:07

标签: node.js mongodb mongoose

我试图获取并过滤数组中的子文档。

该文件具有以下结构:

{
    "_id": {
        "$oid": "58bc4fa0fd85f439ee3ce716"
    },
    "updatedAt": {
        "$date": "2017-03-08T20:39:19.390Z"
    },
    "createdAt": {
        "$date": "2017-03-05T17:49:20.455Z"
    },
    "app": {
        "$oid": "58ae10852035431d5a746cbd"
    },
    "stats": [
        {
            "meta": {
                "key": "value",
                "key": "value"
            },
            "_id": {
                "$oid": "58bc4fc4fd85f439ee3ce718"
            },
            "data": "data",
            "updatedAt": {
                "$date": "2017-03-05T17:49:56.305Z"
            },
            "createdAt": {
                "$date": "2017-03-05T17:49:56.305Z"
            }
        },
        {
            "meta": {
                "key": "value",
                "key": "value"
            },
            "_id": {
                "$oid": "58c06bf79eaf1f15aafe39d0"
            },
            "data": "data",
            "updatedAt": {
                "$date": "2017-03-08T20:39:19.391Z"
            },
            "createdAt": {
                "$date": "2017-03-08T20:39:19.391Z"
            }
        }
    ]
}

我想得到的是两个日期之间的stats数组中的子文档 我试过mongoose查询链:

Model.findById(id)
  .select('stats')
  .where('stats.createdAt').gt(data-value).lt(data-value)

但结果总是包含所有子文档的完整文档。

我也试过这样的聚合:

  Model.aggregate({ 
    $match: { 
      'stats.createdAt': '2017-03-05T17:49:56.305Z' 
    } 
  })

结果始终为null

1 个答案:

答案 0 :(得分:0)

您的结果为空,因为'2017-03-05T17:49:56.305Z'String,您正在寻找Datenew Date('2017-03-05T17:49:56.305Z')

您可以使用$unwind$match的日期范围过滤子文档:

var startDate = new Date('2017-03-05T17:49:56.305Z');
var endDate = new Date('2017-03-08T17:49:56.305Z');

Model.aggregate([{
    $match: {
        "_id": new mongoose.mongo.ObjectId("58bc4fa0fd85f439ee3ce716"),
        "stats.createdAt": {
            $gte: startDate,
            $lt: endDate
        }
    }
}, {
    $unwind: "$stats"
}, {
    $match: {
        "stats.createdAt": {
            $gte: startDate,
            $lt: endDate
        }
    }
}], function(err, res) {
    console.log(res);
})

使用$filter更简单:

Model.aggregate([{
    $match: {
        "_id": new mongoose.mongo.ObjectId("58bc4fa0fd85f439ee3ce716"),
        "stats.createdAt": {
            $gte: startDate,
            $lt: endDate
        }
    }
}, {
    $project: {
        "stats": {
            $filter: {
                input: "$stats",
                as: "stat",
                cond: {
                    $and: [
                        { $gte: ["$$stat.createdAt", startDate] },
                        { $lte: ["$$stat.createdAt", endDate)] }
                    ]
                }
            }
        }
    }
}], function(err, res) {
    console.log(res);
})