mongoose-populate-virtuals
mongoose-populate-virtuals copied to clipboard
"select" must include foreign key
Hello,
I'm trying to use the plugin because I'm using an existing dataset that doesn't follow Mongoose conventions. Typically, I have this kind of models:
var task = {
Status: 'Done',
UserId: 'bob'
};
var user = {
Username: 'Bob',
Email: '[email protected]'
};
I'd like to use Mongoose to get a task and populate it with the corresponding user using the 'Username' as a key. I tried to use the plugin but the virtual field stays undefined.
Here is the code I wrote to test:
var mongoose = require('mongoose-populate-virtuals')(require('mongoose'));
var Schema = mongoose.Schema;
mongoose.connect('mongodb://....', function (err) {
if (err) {
console.error('unable to connect', err);
return;
}
console.info('connected');
var Task = createTaskModel();
createUserModel();
Task.findOne({_id: '5627f2804209631370fe1376'}, {UserId: 1})
.populate('user')
.exec(function (err, t) {
if (err) {
console.error('unable to find one', err);
return;
}
console.info('Task found: ');
console.log(t.toJSON());
});
});
function createTaskModel () {
var taskSchema = new Schema({
Status: String,
UserId: String
}, {
collection: 'tasks',
toJSON: {virtuals: true},
toObject: {virtuals: true}
});
taskSchema.virtual('testVirt').get(function () {
return 'Test Virtual Field';
});
taskSchema.virtual('user', {
ref: 'User',
foreignKey: 'Username',
localKey: 'UserId',
select: 'Email'
});
return mongoose.model('Task', taskSchema);
}
function createUserModel () {
var userSchema = new Schema({
_id: String,
Username: String,
Email: String
}, {
collection: 'users'
});
return mongoose.model('User', userSchema);
}
The output is:
Task found:
{ _id: 5627f2804209631370fe1376,
UserId: 'e.apiyo',
user: undefined,
testVirt: 'Test Virtual Field',
id: '5627f2804209631370fe1376' }
Moreover if I try to "debug" the plugin, I can see that the user is correctly loaded. In the assignVals
method, I can output the different parameters and there is this undefined
key that looks strange:
path >> user
docs >> [ { _id: 5627f2804209631370fe1376,
UserId: 'e.apiyo',
user: 'undefined' } ]
subdocs >> { undefined:
[ { FirstName: 'Eric',
Email: '[email protected]',
_id: '0#te�\u001a�A�fjw\u001d\u0010+�' } ] }
options >> { model:
{ [Function: model]
hooks: { _pres: {}, _posts: {} },
base:
{ connections: [Object],
plugins: [],
models: [Object],
modelSchemas: [Object],
options: [Object] },
modelName: 'User',
model: [Function: model],
db:
{ base: [Object],
collections: [Object],
models: [Object],
config: [Object],
replica: false,
hosts: null,
host: 'localhost',
port: 27017,
user: undefined,
pass: undefined,
name: 'airtelke-globetrotter-db',
options: [Object],
otherDbs: [],
_readyState: 1,
_closeCalled: false,
_hasOpened: true,
_listening: false,
_events: {},
db: [Object] },
discriminators: undefined,
schema:
{ paths: [Object],
subpaths: {},
virtuals: [Object],
singleNestedPaths: {},
nested: {},
inherits: {},
callQueue: [Object],
_indexes: [],
methods: {},
statics: {},
tree: [Object],
_requiredpaths: [],
discriminatorMapping: undefined,
_indexedpaths: undefined,
s: [Object],
options: [Object],
_events: {} },
collection:
{ collection: [Object],
opts: [Object],
name: 'users',
collectionName: 'users',
conn: [Object],
queue: [],
buffer: false,
emitter: [Object] } },
_docs: { '5627f2804209631370fe1376': 'e.apiyo' },
options: undefined,
arrayPop: undefined,
localKey: 'UserId',
foreignKey: 'Username',
select: 'Email FirstName',
match: undefined,
path: 'user' }
assignmentOpts >> { sort: undefined, excludeId: false }
Am I doing something wrong or is there something broken?
Thank you!
Where you select: 'Email'
change to select: 'Email Username'
. I think what is happening is the foreignKey field isn't being returned because it's not selected. Just a guess... the code looks correct otherwise.
Indeed, it helped to add the Username
in the select: when debugging, I can see that the final promise is resolved with an object correctly populated. (in the Model.populate
method)
However in my main script the attribute is still undefined. It's like the property was overridden afterwards.
Do you have any idea what I could investigate?
Btw I'm using Mongoose 4.4.3 (+ MongoDB driver 2.1.7). On which version did you test?
I realized the property was deleted in the init
pre middleware line 35 and the virtual getter is not called when I access the attribute. This is why I got an undefined. If I remove the delete line, then I can access the populated field.
I don't really understand why the getter is not called... Any idea?
"select" must include "foreignKey".
this case {select: 'Email'} change to {select: 'Email Username'}
Can add auto append foreignKey as _id?