更好地限制聚合调用中字段属性的方法

时间:2018-04-27 12:57:56

标签: javascript node.js mongodb mongoose

因此,我尝试在MongoDB中执行aggregate调用以查找集合,但同时限制从其他集合中获取的数据量。这是我尝试的有效方法:

getFamilyStats: function (req, res) {
    Families
        .aggregate([
            { $match: { 'centralPath': req.body.centralPath }},
            { $lookup: {
                from: 'models',
                localField: 'centralPath',
                foreignField: 'centralPath',
                as: 'models'
            }},
            { $unwind: '$models'},
            { $project: {
                'models.openTimes.user': 1,
                '_id': 1,
                'centralPath': 1,
                'totalFamilies': 1,
                'unusedFamilies': 1,
                'oversizedFamilies': 1,
                'inPlaceFamilies': 1,
                'families': 1
            }}
            ]
        ).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);
        });
},

所以效果很好的事实是我可以使用lookup来加入"来自不同集合的数据,在本例中称为模型。一旦我unwind它几乎看起来我想要它,除了我只对该属性中的一个字段感兴趣:models.openTimes并且在这个特殊情况下实际上只是该字段的一个属性{{ 1}}。我试图使用user来限制我从模型中传递的大部分数据,但这迫使我拼出所有其他字段,如下所示:

project

如果我的收藏扩展了新的属性,这并不理想。我正在寻找一种方法将数据从_id: 1, centralPath: 1.... 限制为只有一个字段/一个属性,但是从models集合中获取所有字段。

想法?

家庭的样本数据:

families

模型的示例数据:

{
    "_id" : ObjectId("5ae08c75d132ac4442520672"),
    "centralPath" : "some path",
    "totalFamilies" : 0,
    "unusedFamilies" : 0,
    "oversizedFamilies" : 0,
    "inPlaceFamilies" : 0,
    "families" : [],
    "__v" : 0
}

2 个答案:

答案 0 :(得分:6)

从MongoDB v3.6开始,您可以直接限制$lookup返回的字段:

db.families.aggregate([
    { $match: { 'centralPath': 'some path' } },
    { $lookup: {
        from: 'models',
        let: { centralPath: '$centralPath' }, // remember the value of the "centralPath" field
        pipeline: [
            { $match: { $expr: { $eq: [ '$centralPath',  '$$centralPath' ] } } }, // this performs the "join"
            { $project: { _id: 0, 'openTimes.user': 1 } } // only retrieve the "openTimes.user" field
        ],
        as: 'models'
    }},
    { $unwind: '$models'},
]);

答案 1 :(得分:1)

您可以在3.4及以上版本中尝试以下聚合。

$addFields返回已加入集合中的唯一字段,同时保留现有字段,并$project除外以删除已加入的集合数据。

用addFields和项目阶段替换项目阶段。

Families.aggregate([
 existing stages,
  {"$addFields":{
    "user":"$models.openTimes.user"
  }},
  {"$project":{"models":0}}
])