Mongoose Populate Returns Some Empty Objects

759
December 24, 2016, at 4:47 PM

I have 1 main collection and 1 collection with a ref to the main one. Code looks like :

// Ref schema
    const onlineSchema = mongoose.Schema({
        _id: {
            type: Number,
            ref: 'Player',
            unique: true
        }
    }, {
        timestamps: true
    });
//main schema
const playerSchema = mongoose.Schema({
_id: { // User ID
    type: Number,
    required: true,
    unique: true,
    default: 0
},
firstname: {
    type: String
},
name: {
    type: String,
    required: true
},
lastname: {
    type: String
},
barfoo: {
   type: Boolean
}
...
})

I populate it with this code :

var baz = bar;
...
        Online.find().populate({
            path: '_id',
            match: {
                [ baz + 'foo']: true
            }
        }).exec(function(err, online) {
            if (err) {
                winston.error(err);
            } else {
                winston.error(util.inspect(online, {
                    showHidden: false,
                    depth: null
                }));
            }
        });

If there are 10 elements in online and only 7 match [ baz + 'foo']: true I get 7 proper arrays and 3 empty arrays that look like this:

    { updatedAt: 2016-12-23T18:00:32.725Z,
createdAt: 2016-12-23T18:00:32.725Z,
_id: null,
 __v: 0 },

Why is this happening and how to I filter the final result so it only shows the matching elements?

I can use filter to remove the null arrays after I get the result but I'd like to know how to prevent the the query from passing null arrays in the first place.

Answer 1

Why is this happening ?

This is happening because you get all the documents with Online.find() but the player will be populated only for records that match your condition. Your match is for the populate, not for the find() query.

How do I filter the final result so it only shows the matching elements ?

You cant find a nested elements of a referenced collections since there is no join in MongoDB. But you can :

  • keep your schema and use aggregation with $lookup :

    Online.aggregate(
        [{
            $lookup: {
                from: "players",
                localField: "_id",
                foreignField: "_id",
                as: "players"
            }
        }, {
            $unwind: "$players"
        }, {
            $match: {
                'players.barfoo': true
            }
        }],
        function(err, result) {
            console.log(result);
        });
    
  • change your schema to include Player as a subdocument :

    const playerSchema = new mongoose.Schema({
        //...
    });
    const onlineSchema = new mongoose.Schema({
        player: playerSchema
    }, {
        timestamps: true
    });
    var Online = mongoose.model('Online', onlineSchema);
    Online.find({'player.barfoo':true}).exec(function(err, online) {
        console.log(online);
    });
    
Answer 2

Dont make _id the reference of another schema, instead make another field name player and give reference through that.

const onlineSchema = mongoose.Schema({
    player: {
        type: Number,
        ref: 'Player',
        unique: true
    }
}, {
    timestamps: true
});

Population:

Online.find().populate({
    path: 'player',
    match: {
        [ baz + 'foo']: true
    }
}).exec(...);
Rent Charter Buses Company
READ ALSO
Exit from child, parent and grand parent function

Exit from child, parent and grand parent function

I have a page that lists the names and other details of a number of videosA user, who has already logged-in can click on the name of this video, to add the particular video to his/her portfolio

344
multiple jquery ui slider

multiple jquery ui slider

Hi I want to add jquery slider in a wordpress metabox repeater so I don't know how many jquery slider I 'll have

495