Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose Aggregation match an array of objectIds

I have a schema that Looks like this

var Post = new mongoose.Schema({
    author: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    },
    created: {
        type: Date,
        Default: Date.now
    })

I have a User Table as well. I Have a array of user ids and i am trying to search the post table based on an array of user ids

For Example

var userIds = ["575e96652473d2ab0ac51c1e","575e96652473d2ab0ac51c1d"] .... and so on 

I want to return all posts created by these users. And posts should be sorted by their creation date. Is there a way to group this post based on the user ids provided, basically match the posts for an individual user?

The result I am trying to attain is something like this:

 [{
    userAId : "56656.....",
    post : [postA, postB],
   },{ 
    userBId :"12345...", 
    post : [postA, postB]
}]

How do I write this query?

This is what I have so far

Post.aggregate([{
  // {"$unwind" : ""},
    // "$group": {
    //     _id: "$author",
    //     "created" : {"$sum" : 1 }
    // }
    "$match" : { author : id}
}]).exec(function(error, data) {
  if(error){
    return console.log(error);
  }else{
    return console.log(data)
  }
})



{
    "_id" : ObjectId("575e95bc2473d2ab0ac51c1b"),
    "lastMod" : ISODate("2016-06-13T11:15:08.950Z"),
    "author" : ObjectId("575dac62ec13010678fe41cd"),
    "created" : ISODate("2016-06-13T11:15:08.947Z"),
    "type" : "photo",
    "end" : null,
    "commentCount" : 0,
    "viewCount" : 0,
    "likes" : 0,
    "tags" : [],
    "title" : "Today is a good day",
    "__v" : 0
}
like image 223
unwosu Avatar asked Jun 13 '16 14:06

unwosu


People also ask

What does Mongoose aggregate return?

Returns: A cursor to the documents produced by the final stage of the aggregation pipeline operation, or if you include the explain option, the document that provides details on the processing of the aggregation operation. If the pipeline includes the $out operator, aggregate() returns an empty cursor.

What is $Push in mongoose?

The $push operator appends a specified value to an array. The $push operator has the form: { $push: { <field1>: <value1>, ... } } To specify a <field> in an embedded document or in an array, use dot notation.

Can I use $in in mongoose?

For such cases, mongoose provides the $in operator. In this article, we will discuss how to use $in operator. We will use the $in method on the kennel collection. For performing HTTP endpoint testing, we will use the postman tool.


1 Answers

To return all posts created by users depicted in a list of ids, use the $in operator in your query and then chain the sort() method to the query to order the results by the created date field:

Post.find({ "author": { "$in": userIds } })
    .sort("-created") // or .sort({ field: 'asc', created: -1 });
    .exec(function (err, data){
        if(err){
            return console.log(err);
        } else {
            return console.log(data);
        }
    });

To get a result where you have the post id's grouped per user, you need to run the following aggregation operation:

Post.aggregate([
    { "$match" : { "author": { "$in": userIds } } },
    { "$sort": { "created": -1 } },
    {
        "$group" : {
            "_id" : "$author",
            "posts" : { "$push": "$_id" }
        }
    },
    {
        "$project": {
            "_id": 0,
            "userId": "$_id",
            "posts": 1
        }
    }
]).exec(function (err, result){
    if(err){
        return console.log(err);
    } else {
        return console.log(result);
    }
});

Or with the fluent API:

 Post.aggregate()
    .match({ "author": { "$in": userIds } })
    .sort("-created")
    .group({
        "_id" : "$author",
        "posts" : { "$push": "$_id" }
     })
    .project({
        "_id" : 0,
        "userId" : "$_id",
        "posts": 1
     })
    .exec(function (err, result){
        if(err){
            return console.log(err);
        } else {
            return console.log(result);
        }
    });
like image 167
chridam Avatar answered Sep 30 '22 21:09

chridam