【问题标题】:Can I apply forEach in aggregate query in MongoDB?我可以在 MongoDB 的聚合查询中申请 forEach 吗?
【发布时间】:2016-11-24 14:02:25
【问题描述】:

我有一个成员集合,通过特定条件查找成员,获取成员后我需要对每个成员进行一些计算。在同一个集合上计算需要查询。

我的过程是

var eachMemberInfo = [];
var members = db.collection('member').find({ createdDate: currentDate, country: 'BD'}).toArray();
members.forEach(function(doc) {
  var result = db.collection('member').aggregate([
    { $match: { memberType: doc.memberType, country : doc.country } },
    {
      $group: {
        _id: {memberType:"$memberType",country:"$country"},
        memberCount: { $sum: {$cond:[{$gt: ["$numberOfInvitees",0]},1,0]} },
        lessCount: { $sum: {$cond:[{$and:[{$lt:["$numberOfInvitees", doc.numberOfInvitees]}, {$gt: ["$numberOfInvitees",0]}]},1,0]} },
        sameCount: { $sum: {$cond:[{$eq: ["$numberOfInvitees",doc.numberOfInvitees]},1,0]} }
      }
    }
  ]).toArray();

   eachMemberInfo.push({memberId:doc.memberId,memberCount: result[0].memberCount, lessCount: result[0].lessCount});

});

我的问题是如何使用单个聚合查询来做到这一点?

谁能帮帮我:)

例如:

会员收藏喜欢:

[{
    "_id" : ObjectId("57905b2ca644ec06142a8c06"),
    "memberID" : 80,
    "memberType" : "N",
    "numberOfInvitees" : 2,
    "createdDate" : ISODate("2016-07-21T00:00:00.000Z"),
    "country" : "BD"
},
{
    "_id" : ObjectId("57905b2ca644ec06142a8c09"),
    "memberID" : 81,
    "memberType" : "N",
    "numberOfInvitees" : 3,
    "createdDate" : ISODate("2016-07-21T00:00:00.000Z"),
    "country" : "BD"
}
{
    "_id" : ObjectId("57905b2ca644ec06142a8fgh"),
    "memberID" : 82,
    "memberType" : "N",
    "numberOfInvitees" : 4,
    "createdDate" : ISODate("2016-07-21T00:00:00.000Z"),
    "country" : "BD"
}
{
    "_id" : ObjectId("57905b2ca644ec06142a8cfgd"),
    "memberID" : 83,
    "memberType" : "N",
    "numberOfInvitees" : 1,
    "createdDate" : ISODate("2016-07-21T00:00:00.000Z"),
    "country" : "BD"
}
{
    "_id" : ObjectId("57905b2ca644ec06142a8cfgd"),
    "memberID" : 84,
    "memberType" : "N",
    "numberOfInvitees" : 2,
    "createdDate" : ISODate("2016-07-21T00:00:00.000Z"),
    "country" : "BD"
}
..............
]

eachMemberInfo 中的预期结果如:

[
  { memberID : 80, memberCount:5,lessCount: 1,sameCount:2 },
  { memberID : 81, memberCount:5,lessCount: 3,sameCount:1 },
  { memberID : 82, memberCount:5,lessCount: 4,sameCount:1 },
  { memberID : 83, memberCount:5,lessCount: 0,sameCount:1 },
  { memberID : 84, memberCount:5,lessCount: 1,sameCount:2 }
]

【问题讨论】:

    标签: node.js mongodb aggregation-framework


    【解决方案1】:

    聚合管道无法做到这一点。你应该明白 MongoDB 聚合是一系列应用于集合的特殊运算符。当您执行聚合管道时,MongoDB 将运算符相互传递,即运算符的输出成为以下运算符的输入。每个运算符的结果是一个新的文档集合。

    因此,您在上面尝试实现的目标可以简单地重写为以下管道,而无需先创建文档数组:

    var collection = db.collection('member'), 
        pipeline = [
            { "$match": { createdDate: currentDate, country: 'BD' } },
            {
                "$group": {
                    "_id": { "memberType": "$memberType", "country": "$country" },
                    "memberCount": { 
                        "$sum": { "$cond":[ { "$gt": ["$numberOfInvitees", 0] }, 1, 0 ] } 
                    },
                    "sameCount": { "$sum": 1 } 
                }
            }
        ];
    
    collection.aggregate(pipeline, function(err, result){
        if (err) throw err;
        console.log(result);
    });
    

    更新

    跟进您的问题的更改,运行以下聚合管道将为您提供所需的结果:

    var collection = db.collection('member'), 
        pipeline = [   
            { "$match": { createdDate: currentDate, country: 'BD' } },
            {
                "$group": {
                    "_id": { 
                        "memberType": "$memberType", 
                        "country": "$country" 
                    },            
                    "invitees":{ 
                        "$push":  {
                            "memberID": "$memberID",
                            "count": "$numberOfInvitees"
                        }
                    },
                    "inviteesList": { "$push": "$numberOfInvitees" },
                    "memberCount": { "$sum": 1 } 
                }
            },
            { "$unwind": "$invitees" },
            { "$unwind": "$inviteesList" },
            { 
                "$group": {
                    "_id": "$invitees.memberID",
                    "sameInviteesCount": { 
                         "$sum": { 
                            "$cond": [ 
                                { "$eq": ["$inviteesList", "$invitees.count"] }, 
                                1, 0 
                            ] 
                        }
                    },
                    "lessInviteesCount": { 
                        "$sum": { 
                            "$cond":[ 
                                { "$lt": ["$inviteesList", "$invitees.count"] }, 
                                1, 0 
                            ] 
                        }
                    },
                    "memberCount": { "$first": "$memberCount" }
                }
            }
        ];
    
    collection.aggregate(pipeline, function(err, result){
        if (err) throw err;
        console.log(result);
    });
    

    【讨论】:

    • 感谢您的转发@chridam 如果我们想计算这个lessCount: 我该如何申请?更新了我的问题
    • 您的查询返回带有_id, memberCount, sameCount 的单个对象,但我需要为每个成员提供memberCount, sameCount
    • 我发布了另一个与此问题相关的问题。你能帮我吗@chirdam stackoverflow.com/questions/38502794/…
    • 如果我们添加skiplimit 来查找成员,查询会发生什么变化?喜欢:var members = db.collection('member').find({ createdDate: currentDate, country: 'BD'}).skip(size).limit(1000).toArray(); 但我的 aggregate 查询没有变化@chridam
    • @shaishabroy 要向聚合查询添加跳过和限制,请使用 $limitskip 管道运算符。不知道你的结果会如何,因为你有数据手,你为什么不试一试,看看结果如何?
    猜你喜欢
    • 2020-09-18
    • 2017-02-06
    • 2022-10-04
    • 2019-06-18
    • 2017-08-06
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多