Waterline MongoDb (populated) fetched object looses its type AND prototype functions

主宰稳场 提交于 2019-12-08 02:13:51

问题


I'm using sails with mongo db over waterline.

Lets say that I declare 2 models in my sails project like so :

A user model @ models/User.js simplified:

username: {
        type: 'string',
        unique: true
 },
passports: {
        collection: 'Passport',
        via: 'owner'
},

aUserFunction: function(){       
    console.log('I'm a user function');
}

and a passport model @ models/Passport.js simplified:

password: {
      type: 'string'
 },

owner: {
      model: 'User',
      required: true
 },

aPassportFunction: function(){
    console.log('I'm a passport function');
}

So far so good.

When I fetch one of those associated objects I do it like so:

sails.models.user
.findOne({ username: 'aUsername' })
.populate('passports') // The populate method allows you to get associated data
.exec(function (err, myUser) {
    ...
    JSON.stringify(myUser);   //The object returns just fine!
    ...
}

As expected the returned myUser object is this:

{
    username:"aUsername",
    passports: 
    [
        {
            password: 'aPass',
            owner: 'theUsersId'
        }
    ]            
}

I can now run myUser.aUserFunction(); as expected, since myUser is of type models/User.js.

If I try to get my hands on the specific passport I can do this: var passport = myUser.passports[0];

The problem:

Trying to run passport.aPassportFunction(); is impossible, since the returned object is of type Object and not models/Passport.js.

Now from what I know theres NO type casting in javascript, and that would be a wonderful time to use it.

I wouldn't like to copy paste the values into a new object in order to use the aPassportFunction(), it seems like a waste of resources.

Is there any other way to cast this generic passport Object as models/Passport.js type.


回答1:


mongodb actually should not store anything besides data, and so it shouldnt store any functions:

Problems storing JS functions in Mongo DB with Node.js

But the reason why myUser.aUserFunction() works, i believe, is because waterline's findOne actually transforms the object into the waterline object, not what is actually stored in mongodb. Mongodb will only return you a flat file. If you do a mongodb query you will find that your populated association doesn't even exist under the parent object.

So you are limited to what waterline allows you to do.

One suggestion is instead of using the waterline one-to-many association, make a mongodb one-to-many association instead:

myuser.js:

{
  username:"aUsername",
  passports: 
    [
      ObjectId("passportid"),
      ObjectId("passportid")
    ]            
}

Then you will be able to leverage waterline's findOne on the passport object id and get the Passport.js object, instead of a User.js object with only Passport's data embedded.

Details: https://www.safaribooksonline.com/blog/2012/12/18/document-oriented-data-modeling-with-mongodb/



来源:https://stackoverflow.com/questions/30526939/waterline-mongodb-populated-fetched-object-looses-its-type-and-prototype-funct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!