island205
island205

Reputation: 1740

Assign property value doesn't work in Mongoose

My query is:

db.Room.find({}, function (err, rooms) {
  if (!err) {
    async.each(rooms, function (room, done) {
      db.User.find({}, function (err, users) {
        if (err) {
          done(err)
        } else {
          room.users = users
          room._name = room.name
          done()
        }
      })
    }, function (err) {
      if (!err) {
        socket.emit('read:rooms', rooms)
      }
    })
  }
})

and schemas are:

room:

var mongoose = require('mongoose')
var Schema = mongoose.Schema,
  ObjectId = Schema.ObjectId;

var Room = new Schema({
  name: String
});

module.exports = Room

user:

var mongoose = require('mongoose')
var Schema = mongoose.Schema,
  ObjectId = Schema.ObjectId;

var User = new Schema({
  email: String
});

module.exports = User

but in front-end:

  socket.on('read:rooms', function (rooms) {
    $scope.rooms = rooms
  })

but rooms has no users property, help me, please

Upvotes: 1

Views: 2604

Answers (1)

WiredPrairie
WiredPrairie

Reputation: 59763

It's because the Rooms schema doesn't have a users property.

So, there are a few ways to fix it. Since it looks like though you want the users property to be something that really isn't part of the schema, and is a client-side join rather than work that is done on the database (which is a good!), I'd suggest you convert the data to be just plain old JavaScript objects when you send it over the socket (this would have happened anyway, you're just doing it a bit earlier).

So, when the find returns, it is actually returning a fully-realized MongooseJS model object. While you can set dynamic properties on the object instance, they aren't part of the "data" of the model, so that when it is serialized later to the client, only the properties that are documented will be available.

So, here is an example of what I'd suggest:

db.Room.find({}, function (err, rooms) {
  if (!err) {
    var oRooms = [];
    async.each(rooms, function (room, done) {
      /* etc. your code */

       } else {
          var oRoom = room.toObject();
          oRoom.users = users
          oRoom._name = room.name
          oRooms.push(oRoom);
          done()
       }

This technique would use the toObject functionality of a Model to return a JavaScript object (not a Mongoose model). That way, you can do what you'd like to the object, including adding new properties dynamically.

Later, of course, make sure you send the new array of rooms to the client:

 if (!err) {
    socket.emit('read:rooms', oRooms)
 }

Upvotes: 4

Related Questions