5

In my route I am trying to replace a value in whatever i get from the database before sending it to my view.

In this case I am trying to replace a reference to a user, with the users username instead. But my console.log's just keep returning the value unchanged.

app.get('/message/inbox', function(req, res) {
    var _id = req.user._id;
    var inbox = null;
    var users = null;
    async.parallel([
        function(callback){
            Inbox.find({to: _id}, callback);
        },
        function(callback){
            User.find({}, callback);
        }
    ],
    function(err, result){
        inbox = result[0];
        users = result[1];
        for(var i = 0; i < inbox.length; i++) {
            for(var j = 0; j < users.length; j++) {
                if(String(inbox[i].from) == String(users[j]._id)) {
                    inbox[i].from = users[j].local.username;
                    console.log(users[j].local.username);
                    console.log(inbox[i].from);
                    break;
                }
            } 
        }
        console.log(inbox);
    });
});

This is what my console returns:

some@email.com
540468daeb56d5081ade600d
[ { _id: 54084cacf212815422aabe94,
    from: 540468daeb56d5081ade600d,
    to: 5406bf4c8a8acc88120922dc,
    headline: 'Some Headline',
text: 'Some text',
__v: 0 } ]
Cœur
  • 37,241
  • 25
  • 195
  • 267
Jesper Pannerup
  • 134
  • 3
  • 11
  • possible duplicate of https://stackoverflow.com/questions/9952649/convert-mongoose-docs-to-json – Deepak Jan 31 '20 at 07:05

3 Answers3

7

What gets returned from the find requests is a "mongoose document" which is actually quite complex and contains all the rules and methods from the associated schema. You cannot modify this outside of the constraints set on the schema.

So despite the simple serialized form, the object is quite complex. What you want is just a basic object, so you can modify it however you want. So put simply, just call .toObject() to get the "raw" JavaScript object without the rest of the sugar:

inbox = result[0].toObject();
users = result[0].toObject();

The basic objects have no methods and no rules. Modify away.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
  • I found this solution other places, but it kept returning "has no method 'toObject'" – Jesper Pannerup Sep 05 '14 at 08:32
  • @JesperNielsen Then why change your title to (solved)? It either works or it doesn't – Neil Lunn Sep 05 '14 at 08:36
  • @NielLunn - Look at my updated post. I found my own solution. – Jesper Pannerup Sep 05 '14 at 10:23
  • @JesperNielsen Still don't understand why this is not a solution as it works for me and everyone else using mongoose. Of course you can just manually assign every property to a new object as you have done, but I don't call that a solution. – Neil Lunn Sep 05 '14 at 10:35
  • I later got it to work. I had a problem where I didn't have access to any of the mongoose functions. I have solved this now and .toObject works as it should now. – Jesper Pannerup Oct 22 '14 at 10:13
3

Solution by OP.

I just have to add a .lean() after the .find. This tells mongoose to pass the data as a javascript object instead of a MongooseDocument - Scource

app.get('/message/inbox', function(req, res) {
    var _id = req.user._id;
    var inbox = null;
    var users = null;
    async.parallel([
        function(callback){
            Inbox.find({to: _id}, callback).lean();
        },
        function(callback){
            User.find({}, callback).lean();
        }
    ],
    function(err, result){
        inbox = result[0];
        users = result[1];
        for(var i = 0; i < inbox.length; i++) {
            for(var j = 0; j < users.length; j++) {
                if(String(inbox[i].from) == String(users[j]._id)) {
                    inbox[i].from = users[j].local.username;
                    console.log(users[j].local.username);
                    console.log(inbox[i].from);
                    break;
                }
            } 
        }
        console.log(inbox);
    });
});
Cœur
  • 37,241
  • 25
  • 195
  • 267
0
/*
 you just need to add .lean() at the end of mongoose query where you want to change the object later stage.
*/
let forExample = aysnc (req, res, next ) => {
let foundUser = await user.find({ organisationId: 10 }); // without lean
foundUser.map(elem => {
  elem.userName = elem.name;
  delete elem;
});
console.log(foundUser[0]); // it will return { name:'something'};
// but if you try:
let foundUser = await user.find({ organisationId: 10 }).lean();// with lean
foundUser.map(elem => {
  elem.userName = elem.name;
  delete elem;
});
console.log(foundUser[0]); // it will return { userName:'something'};
zshan4444
  • 380
  • 3
  • 7