NodeJS聚合2个特定过滤器

时间:2017-02-12 17:22:01

标签: node.js mongodb mongoose mongodb-query aggregation-framework

我有两个模型,一个叫做追随者,一个称为时间轴。我想要做的是获取关注者的时间表,并按照关注者包含的密钥过滤该时间线内的帖子。

以下是我的模特:

var followerSchema = new Schema({
    followee: { type: Schema.ObjectId, ref: 'User' },
    follower: { type: Schema.ObjectId, ref: 'User' },
    accepted: Boolean,
    branches: [],
    date: { type: Date, default: Date.now }
});

var timelineSchema = new Schema({
    user: { type: Schema.ObjectId, ref: 'User' },
    posts: [],
});

以下是填充模型的外观:

[{ 
    _id: 58a086dc3884d9ddfb65bad8,
    accepted: true,
    follower: 58a086293884d9ddfb65bad2,
    followee: 58a086923884d9ddfb65bad5,
    __v: 0,
    date: Sun Feb 12 2017 11:01:32 GMT-0500 (EST),
    branches: [ 2, 5 ]
 }, ...]

{ 
  _id: '58a086293884d9ddfb65bad3',
  user: '58a086293884d9ddfb65bad2',
  __v: 0,
  posts: [ 
     { date: 1486915113883,
       branch: '-1',
       txt: 'hello 0'},
     { date: 1486915142820,
       branch: '1',
       txt: 'hello 1' },
     { date: 1486915265607,
       branch: '2',
       txt: 'hello 2' } 
  ]
}

目前我正在使用此代码汇总时间轴。

Follower.find({
    followee: req.params.user_id, 
    accepted: true
}, function(err, followees) {
    if (err)
        res.json(err);

    // Create a date 3 days past current date
    var d = new Date();
    d.setDate(d.getDate() - 3);

    // Gets all timelines of the followees and their newest posts
    Timeline.aggregate([
        { $match: { user: {$in : followees.map(function(x) {return x.follower;}) } }},
        { $unwind: '$posts'},
        { $match: {'posts.date': {$gte: d.getTime() } } },
        { $match: {'posts.branch': {$in : ['1', '2', '5']} } }, // <--- this array should be that equal to the followers branches
        { $group: {
                '_id':'$_id',
                'user' : {'$first': '$user'},
                'posts': {'$push': '$posts'} 
            } 
        }
    ]).exec(function(err, timeline) {

        console.log(timeline)

        // Populate the user
        User.populate(timeline, {path: 'user'}, function(err, tt) {
            if (err) 
                res.json(err);

            res.json(timeline);
        })
    });
});

此查询获取了关注者的所有帖子,但我只希望帖子的分支在关注者分支中。

不知怎的,我相信我必须改变这一行

{ $match: {'posts.branch': {$in : ['1', '2', '5']} } }

但不知何故用当前追随者的分支替换数组。

我正在寻找的预期JSON输出如下:

{
    "_id" = 58a086293884d9ddfb65bad3;
    posts = [{
            branch = 1,
            date = 1486915142820,
            txt = "hello 0"
        },
                    {
            branch = 2,
            date = 1486915265607,
            txt = "hello 2",
        }
    ],
    user = {
        "__v" = 0;
        "_id" = 58a086293884d9ddfb65bad2,
        date = "2017-02-12T15:58:33.861Z",
        email = "email@google.com",
        handle = "m",
        password = "m",
    }
}

1 个答案:

答案 0 :(得分:0)

您可以使用$lookup创建与关注者集合的联接,在通过$ lookup创建的新字段中展开分支数组,然后在分支的基础上进行分组。

通过此,您将拥有特定于关注者集合中分支的用户,帖子。

// Gets all timelines of the followees and their newest posts
Timeline.aggregate([
    { $match: { user: {$in : followees.map(function(x) {return x.follower;}) } }},
    { $unwind: '$posts'},
    { $match: {'posts.date': {$gte: d.getTime() } } },
    { $lookup: { 
                 from: "followers",
                 localField: "user",
                 foreignField: "follower",
                 as: "fNew"
               }
    },
    { $unwind: "fNew" },
    { $unwind: "fNew.branches" },
    { $unwind: "posts" },
    { $project: {"isBranchSame":{$eq:["$posts.branch","$fNew.branches"]},"otherFieldsToProject":1}},
    { $match: {"isBranchSame":true}},
    { $group: {
            '_id': "$_id",
            'user' : {'$first': '$user'},
            'posts': {'$push': '$posts'} 
        } 
    }
])