简体   繁体   中英

Node mongoose populate with condition not returns the expected results

I am trying to use the query conditions in populate method. if a condition is used then still all the records are populated but ones that don't satisfy the condition have the populated field is set to null, For example:

var query = BookModel.find();
query.populate('author','name',{name:'author1'});
query.find(function(err,books){
  console.log(books);
});

Then the output is:
[  { author: { _id: 4ea0db52e09aa6aad2e831fe, name: 'author1' },
    title: 'book1',
    _id: 4ea0dbebc191848704000005 },
  { author: null,
    title: 'book2',
    _id: 4ea0dbebc191848704000006 } ,
  { author: null,
    title: 'book3',
    _id: 4ea0dbebc191848704000007 } ,
  { author: null,
    title: 'book4',
    _id: 4ea0dbebc191848704000008 } ]

However, I expect only the 1st record in the output result. How can i solve this problem?

I had same problem which you are facing and I tried the above code but it did not help me solve the problem. I found a way to do it just like you want. You cannot do this kind of filter by using populate, you have to use raw query of mongodb to filter out your data.

// db['result'] is the name of database
db['result'].aggregate([

    // this is just like populate this populate the user field
    {
        $lookup:{
            from:'users',
            localField:'user',
            foreignField:'_id',
            as:'user'
        }
    },
    // unwind convert the array to objects to apply filter on it
    {
        $unwind:{
            preserveNullAndEmptyArrays : true, // this remove the object which is null
            path : "$user"
        }
    },
    // in match you have to define your condition this check if the user has role equals to 3
    {
        $match:{
            "user.role": 3
        }
    },
    {
        // this provide pagination
        $facet: {
            edges: [
                { $skip: sk },
                { $limit: lm },
            ],
            /* pageInfo: [
                { $group: { _id: null, count: { $sum: 1 } } },
            ],*/
        },
    }
], function (err, result) {
    if (err) {
        // this res is send if there is some error
        console.log(err);
        callback(500, err)
    } else {
        // you get the data
        console.log(result);
        callback(200, result)
    }
});

Look if this can helps you, I need more information about the problem, that's a possible solution.

 BookModel.find()
    .populate({
      path: 'author',
      match: { author: 'author1' },
      select: 'name' // I'm suppossing you want to select "name" field, if not, delete this line.
    }).find(function(err,books){
        console.log(books);
    });

or you can do this:

var query = BookModel.find({name: 'author1'});
query.populate('author','name');
query.find(function(err,books){
  console.log(books);
});

You could add an extra query in your results to filter out the nulls:

var query = BookModel.find();
query.populate('author','name',{name:'author1'});
query.find(function(err, books){
    books = books.filter(function(b){ return b.author; });
    console.log(books, null, 4);
});

Console output

[
    {
        "author": {
            "_id": "4ea0db52e09aa6aad2e831fe",
            "name": "author1"
        },
        "title": "book1",
        "_id": "4ea0dbebc191848704000005"
    }
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM