I got a relationship between 2 schemes, for the sake of simplicity lets call it parent => children.
const ChildScheme = new mongoose.Schema(
{
name: { type: String, required: true },
},
{
timestamps:true
});
const child = mongoose.model("Child", Child);
const ParentScheme = new mongoose.Schema(
{
name: { type: String, required: true },
children: [{type: mongoose.Schema.Types.ObjectId, ref: Child, autopopulate: true}],
},
{
timestamps:true
});
Now I want to get a specific child from a specific parent through an the child's id.
What I tried was:
models.Parent.findById('parent_obj_id')
.then((parent) => {
let child = parent.children.id('child_id')
});
This however does not work, children is of the type CoreMongooseArray, which does not have the function id.
I've searched bit through the source code and I can see that the class CoreDocumentArray which extends from CoreMongooseArray does have that function.
Why do I get a CoreMongooseArray? Is this not working because in actual the mongoose
when I execute the following:
models.Parent.findById('parent_obj_id')
.then((parent) => {
console.log(parent);
});
I will get this response:
{ children:
[ { name: [],
_id: 5dbd9723533e204ab91ccee5,
name: 'peter',
createdAt: 2019-11-02T14:48:03.763Z,
updatedAt: 2019-11-02T14:48:03.763Z,
__v: 0 } ],
_id: 5dbd9723533e204ab91ccee3,
name: 'Walter',
createdAt: 2019-11-02T14:48:03.596Z,
updatedAt: 2019-11-02T14:48:03.806Z,
__v: 3 }
After you find the parent, you can access the specific child using javascript array find like this:
models.Parent.findById("parent_obj_id").then(parent => {
let child = parent.children.find(c => c._id.toString() === "child_id");
console.log(child);
//todo: send response
});
I made a simple demo like this:
(I guess you are using https://www.npmjs.com/package/mongoose-autopopulate package for autopopulate feature)
Parent model (Team):
const mongoose = require("mongoose");
const teamSchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true,
trim: true
},
players: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Player",
autopopulate: true
}
]
});
teamSchema.plugin(require("mongoose-autopopulate"));
const team = mongoose.model("Team", teamSchema);
module.exports = team;
Child model: (Player)
const mongoose = require("mongoose");
const playerSchema = new mongoose.Schema({
name: String
});
const player = mongoose.model("Player", playerSchema);
module.exports = player;
I have 3 players like this:
[
{
"_id": "5dbdb7cf0101fb08b434a576",
"name": "player 1",
"__v": 0
},
{
"_id": "5dbdb7d80101fb08b434a577",
"name": "player 2",
"__v": 0
},
{
"_id": "5dbdb7e00101fb08b434a578",
"name": "player 3",
"__v": 0
}
]
I have 1 team with those 3 players like this:
[
{
"players": [
"5dbdb7cf0101fb08b434a576",
"5dbdb7d80101fb08b434a577",
"5dbdb7e00101fb08b434a578"
],
"_id": "5dbdb80d0101fb08b434a579",
"name": "team 1",
"__v": 0
}
]
To get the team 1's player 1 info, I use the following route:
router.get("/team/:teamId/:playerId", (req, res) => {
const { teamId, playerId } = req.params;
Team.findById(teamId).then(team => {
const player = team.players.find(p => p._id.toString() === playerId);
res.send(player);
});
});
And the result is:
{
"_id": "5dbdb7cf0101fb08b434a576",
"name": "player 1",
"__v": 0
}