Reputation: 1538
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.
Upvotes: 1
Views: 1305
Reputation: 771
dont use _id to ref field.. because its default filed in mongoDB to create index unique.. change you're field name
Upvotes: 0
Reputation: 45352
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);
});
Upvotes: 2
Reputation: 9268
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(...);
Upvotes: 0