【问题标题】:$project query in MongoDB with mongoose在 MongoDB 中使用 mongoose 进行 $project 查询
【发布时间】:2018-04-03 22:44:48
【问题描述】:

鉴于此文件:

"_id" : ObjectId("5a4ea040825de6c0bbbcc810"),
"onOpened" : [ 
        {
            "createdOn" : ISODate("2018-01-04T21:46:56.756Z"),
            "_id" : ObjectId("5a4ea0d0825de6c0bbbcc828")
        }, 
        {
            "createdOn" : ISODate("2018-01-04T21:57:24.939Z"),
            "_id" : ObjectId("5a4ea344a7513e0d27642494")
        }, 
        {
            "createdOn" : ISODate("2018-01-05T18:27:26.839Z"),
            "_id" : ObjectId("5a4fc38e62a06a8cced22657")
        }]
"onSynched" : [ 
        {
            "createdOn" : ISODate("2018-01-04T21:46:56.756Z"),
            "_id" : ObjectId("5a4ea0d0825de6c0bbbcc828")
        }, 
        {
            "createdOn" : ISODate("2018-01-04T21:57:24.939Z"),
            "_id" : ObjectId("5a4ea344a7513e0d27642494")
        }, 
        {
            "createdOn" : ISODate("2018-01-05T18:27:26.839Z"),
            "_id" : ObjectId("5a4fc38e62a06a8cced22657")
        }]

我正在尝试在 MongoDB/Mongoose 中执行 aggregate 查询,以便我只能选择给定日期范围内的元素。我试过这个:

module.exports.getWorksetStats = function (req, res) {
    var id = req.params.id;
    var from = new Date(req.query.from);
    var to = new Date(req.query.to);
    HealthRecords
        .aggregate(
            [
                {$match: {_id: id}},
                {$project: {
                    'onOpened': {$filter: {
                        input: '$onOpened',
                        as: 'item',
                        cond: {$and: [
                            {$gte: ['$$item.createdOn', from]},
                            {$lte: ['$$item.createdOn', to]}
                        ]}
                    }}
                }}
            ]
        ).exec(function (err, response){
            var result = {
                status: 200,
                message: response
            };
            if (err){
                result.status = 500;
                result.message = err;
            } else if (!response){
                result.status = 404;
                result.message = err;
            }
            res.status(result.status).json(result.message);
        });
};

不幸的是,这似乎返回了一个空数组。谁能想到我在这里做错了什么?

另外,目标是在一个查询中做一些事情,但我想我可以从这个开始。这个想法实际上是: 1.获取onOpened按日期范围过滤, 2.onSynched按日期范围过滤, 3. 另一个集合,但带有$slice: -1

我正在使用 MongoDB 3.4.7 和 Mongoose 4.5.5。

【问题讨论】:

  • 比赛阶段为什么不淘汰?
  • @konrad,您的查询很好。我将示例数据添加到本地,并运行此测试查询db.collection.aggregate([ {$match: {_id: ObjectId("5a4ea040825de6c0bbbcc810")}}, {$project: { 'onOpened': {$filter: { input: '$onOpened', as: 'item', cond: {$and: [ {$gte: ['$$item.createdOn', ISODate("2018-01-04T21:57:24.939Z")]}, {$lte: ['$$item.createdOn', ISODate("2018-01-05T18:27:26.839Z")]} ]} }} }} ]) ,得到正确的输出。我想问题出在你的 javascript 部分。
  • 哈!你说的对。问题是aggregate 不接受字符串形式的 id,这正是我与id = req.params.id 匹配的内容,而您在上面所做的是将其转换为猫鼬ObjectId。我错过了。其他使用 Mongoose 的查询工作得很好,无需转换为 ObjectId
  • 如何将项目应用于两个数组:onSynched 和 onOpened?

标签: node.js mongodb mongoose


【解决方案1】:

试试这个

db.getCollection('TEST').aggregate([{
        $match: {
            _id: id
        }
    },
    {
        $project: {
            onOpened: {
                $filter: {
                    input: "$onOpened",
                    as: "item",
                    cond: {
                        $gte: ['$$item.createdOn', from],
                        $lte: ['$$item.createdOn', to]
                    }
                }
            },
            onSynched: 1
        }
    }
]);

【讨论】:

  • 是的!那可行。我也可以将相同的过滤规则应用于数组的其他部分。谢谢!
  • 请注意上面的评论,id 需要是一个猫鼬对象。
猜你喜欢
  • 1970-01-01
  • 2015-03-13
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 2016-05-30
  • 2018-09-29
  • 2014-10-10
相关资源
最近更新 更多