2
votes

I can't get mongoose to show subdocument when running find() while it displays perfectly well in mongodb shell.

Subdocument should be embedded based on my schema, not objectId referenced, so I shouldn't be running any black magic voodoo to get my data to show up.

const UserSchema = new mongoose.Schema({
  username: String;
  xp: Number;
  //etc.
});

const RoomSchema = new mongoose.Schema({
  timestamp: { type: Date, default: Date.now },
  status: { type: String, enum: ["pending", "ongoing", "completed"]},
  players: {
    type: [{
      points: { type: Number, default: 0 },
      position: String,
      user: UserSchema
    }],
    maxlength:2
  }
});

After adding a new room with:

let room = new Room(coreObj);
room.players.push({
  points: 0,
  position: 'blue',
  user: userObj //where userObj is a result of running findById on User model
});

It displays nicely in mongo shell, when running db.rooms.find({}).pretty() I can see that full document has been added. However, when running on mongoose model:

Room.find({}).exec((err,rooms)=>{
  console.log(rooms[0].toJSON()); 
});

I don't see user subdocument, moreover I cannot see user field entirely! What seems to be the problem?

logged json from mongoose model:

{
    "status": "pending",
    "_id": "5cf5a25c050db208641a2076",
    "timestamp": "2019-06-03T22:42:36.946Z",
    "players": [
        {
            "points": 0,
            "_id": "5cf5a25c050db208641a2077",
            "position": "blue"
        }
    ],
    "__v": 0
}

json from mongo shell:

{
        "_id" : ObjectId("5cf5a25c050db208641a2076"),
        "status" : "pending",
        "timestamp" : ISODate("2019-06-03T22:42:36.946Z"),
        "players" : [
                {
                        "points" : 0,
                        "_id" : ObjectId("5cf5a25c050db208641a2077"),
                        "position" : "blue",
                        "user" : {
                                "xp" : 0,
                                "_id" : ObjectId("5cf2da91a45db837b8061270"),
                                "username" : "bogdan_zvonko",
                                "__v" : 0
                        }
                }
        ],
        "__v" : 0
}
2
What do you mean exactly by "don't see user subdocument"? Please post what you see when you print it to the console.kevinadi
@kevinadi I updated the question accordingly. Any thoughts to steer me in right direction?Aleksa Ilić

2 Answers

1
votes

Keeping best practice in mind, I think it would be more appropriate to reference the UserSchema in the RoomSchema. Something like:

...
user: {
   type: Schema.Types.ObjectId,
   ref: 'UserSchema'
}

Then you would store the user._id in that field.

This way, if the user is modified, your RoomSchema is always referencing the correct information. You could then get the user using Mongoose's populate

0
votes

I'm not entirely sure why you can't see the sub-sub-document, but this code example printed it correctly for me. Example was originally posted in https://mongoosejs.com/docs/subdocs.html but modified slightly to contain sub-sub-document so it looks similar to your code:

var grandChildSchema = new mongoose.Schema({ name: 'string' });

var childSchema = new mongoose.Schema({ name: 'string', grandChild: grandChildSchema });

var parentSchema = new mongoose.Schema({ children: [childSchema] });

var Parent = mongoose.model('Parent', parentSchema);

var parent = new Parent({
  children: [
    { name: 'Matt', grandChild: {name: 'Matt Jr'} },
    { name: 'Sarah', grandChild: {name: 'Sarah Jr'} }
  ]
})

parent.save(function() {
  Parent.find().exec(function(err, res) {
    console.log(JSON.stringify(res[0]))
    mongoose.connection.close()
  })
});

Executing this code resulted in:

{
  "_id": "5cf7096408b1f54151ef907c",
  "children": [
    {
      "_id": "5cf7096408b1f54151ef907f",
      "name": "Matt",
      "grandChild": {
        "_id": "5cf7096408b1f54151ef9080",
        "name": "Matt Jr"
      }
    },
    {
      "_id": "5cf7096408b1f54151ef907d",
      "name": "Sarah",
      "grandChild": {
        "_id": "5cf7096408b1f54151ef907e",
        "name": "Sarah Jr"
      }
    }
  ],
  "__v": 0
}

This was tested using Mongoose 5.5.12.

Note that I was using JSON.stringify() to print the document instead of using Mongoose's toJSON().