here is my schema :
var sourcesSchema = {
title: String,
name: String,
url: String,
description: String,
category: Array,
rating: Number,
source_pages: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'source_page',
}]
}
var sourcePageschema = {
uname: String,
source_name: String,
page_address: String,
driver_name: String,
product: {
type: mongoose.Schema.Types.ObjectId,
ref: 'products' //Edit: I'd put the schema. Silly me.
}
}
var productsSchema = {
title: String,
uname: String,
descriptin: String,
images: Array,
currency: String,
last_update_time: Number,
last_process_time: Number,
meta_data: {},
tags: Array,
min_price: Number,
max_price: Number,
prices: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'prices' //Edit: I'd put the schema. Silly me.
}]
}
this code works and populate the source_pages successfully :
_sources.find().populate('source_pages').exec(function (err,sources) {
res.json(200, sources);
});
but if I want to populate the product too :
_sources.find().populate('source_pages').populate('source_pages.product').exec(function (err,sources) {
res.json(200, sources);
})
this error :
TypeError: Cannot call method 'path' of undefined
at search (/home/sina/rhino2/node_modules/mongoose/lib/model.js:2088:28)
at search (/home/sina/rhino2/node_modules/mongoose/lib/model.js:2107:22)
at Function._getSchema (/home/sina/rhino2/node_modules/mongoose/lib/model.js:2114:5)
at populate (/home/sina/rhino2/node_modules/mongoose/lib/model.js:1719:22)
at Function.Model.populate (/home/sina/rhino2/node_modules/mongoose/lib/model.js:1702:5)
at cb (/home/sina/rhino2/node_modules/mongoose/lib/query.js:1690:11)
at /home/sina/rhino2/node_modules/mongoose/lib/utils.js:414:16
at /home/sina/rhino2/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursor.js:158:16
at commandHandler (/home/sina/rhino2/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursor.js:643:16)
at null. (/home/sina/rhino2/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js:1641:20)
I was just hunting down the same problem, and I believe what you are looking for is this Mongoose: deep population (populate a populated field).
Basically, you are not able to do what you are trying to do, unless you do it in your callback function and then insert it in your return. I was trying to avoid that, but at the moment it seems like the only option. The other option, if you plan on doing a lot of this type of stuff, is to look into using a Relational DB.
Related
I am pretty new to MongoDB and i am unable to find a solution to the following:
I am trying to sort personnel after their ranks.
CollectionPerson: _id, name, {rank_id}
CollectionRank: _id, RankName, level
What I am trying to accomplish ist to get a list in order of the rank level.
Any solution or direction pointing would be nice.
/edit:
MyModels:
const RankSchema = new Schema({
level: Number,
dgGrp: Number,
dgSold: String,
dgNATO: String,
hut: {
bezX: String,
bezM: String,
bezS: String,
img: String
},
lut: {
bezX: String,
bezM: String,
bezS: String,
img: String
},
mut: {
bezX: String,
bezM: String,
bezS: String,
img: String
}
});
const PersonalSchema = new Schema({
name: {
type: String,
required: true,
},
vname: String,
pNum: {
type: String,
default: '01010101',
},
pKenn: {
type: String,
default: '010101-A-01010',
},
dg: {
type: Schema.Types.ObjectId,
required: true,
ref: 'Rank'
},
uni: String,
sex: String,
konf: String,
adresse: {
str: String,
plz: Number,
ort: String,
land: String,
staat: String
}
});
My Query:
const personal = await Personal.find({}).populate({ path: 'dg', options: { sort: { level: 1 } } });
Population is done on client side by Mongoose after the query fetching the base documents has already executed. As such, sorting the base documents has already been done (if requested).
You can:
Construct an aggregation pipeline, $lookup and $sort yourself.
Let Mongoose populate your documents then reorder them as you wish in your application.
I have a Mongo schema which essentially has two nested arrays, each of which contain objects. I would like to create an index on a field nested in that second level array. The schema looks as such:
const restaurantsSchema = new Schema({
restaurantName: { type: String, required: true },
dishes: [{
dishName: String,
price: Number,
description: String,
reviews: [{
reviewId: Number, **<<<< INDEX THIS FIELD**
userId: {
type: Schema.Types.ObjectId,
ref: 'users',
required: true,
},
photoUrl: String,
caption: String,
createdAt: Number,
updatedAt: Number,
rating: Number,
reviewText: String,
}],
}],
});
The idea is that I can use this index to find and update a user's reviews. Is this possible with Mongo's multikey indexing or is there another way to do this? Any help would be appreciated.
I believe if you change the schema to
reviewId: {
type: Number,
unique: true
}
mongodb automatically creates an index because each value should be unique. That really the only qualification for creating any index.
write back if it works!
I want to insert a document in my database from a website form. I have a model created with mongoose and I want to save in the database only the attributes that contains data and I don't want to save empty attributes.
This is my model:
const localizationSchema = new Schema({
name: { type: String, required: true },
spins: [{ type: String }],
spinsForChild: [{ type: String }],
parent: { id: String, name: String },
localizationType: { type: String },
count: { type: Number, default: 0 },
countries: [{ id: String, name: String, cities: [{ id: String, name: String }] }]
});
const Localization = mongoose.model('Localization', localizationSchema);
When I try to save a new document, it creates in the database all attributes although I don't send it on my query.
Localization.create({
name: body.name,
localizationType: body.localizationType,
"parent.id": parent.id,
"parent.name": parent.name,
spins: spins,
spinsForChild: spinsForChild
}, function(err) {
if (err) return handleError(err);
res.redirect('/localizations');
});
This code, for example, inserts in the DB an empty array called "countries".
I tried to use strict: false in the model declaration but it didn't works.
You could use this answer.
But, thing you try to implement seems to be anti-pattern and can cause errors when you will try to use array update operators with undefined array. So, use it carefully.
Good luck!
This is my mongo schema, I'm trying to update yes/no/usersId with multiple value
var answersSchema = mongoose.Schema({
questionId: String,
usersId: Array,
yes: Array,
no: Array,
white: Array,
created : { type: Number, default: (new Date()).getTime() },
});
and this is my operation
answer.update({
$addToSet: {
uersId: data.userId,
yes: data.userId
}
}, function(updateResponse){
console.log('---------------------------------------> cb yes update',updateResponse)
result.answer = answer;
if (cb !== undefined && cb !== null) {
cb(result);
}
})
and this is my error
Cannot apply $addToSet modifier to non-array
I know it's something stupid maybe I'm tired maybe someone know the problem.
this is my new mongo answer schema
var answersSchema = mongoose.Schema({
questionId: String,
usersId: [{ type: String, ref: 'Users' }],
yes: [{ type: String, ref: 'Users' }],
no: [{ type: String, ref: 'Users' }],
white: [{ type: String, ref: 'Users' }],
created : { type: String, default: (new Date()).getTime() },
});
i define the field into the array, so it's work fine
can someone please help me with population of this schema? I need to populate array of Staff by their userId.
var PlaceSchema = new Schema ({
name: { type: String, required: true, trim: true },
permalink: { type: String },
country: { type: String, required: true },
...long story :D...
staff: [staffSchema],
admins: [adminSchema],
masterPlace:{ type: Boolean },
images: []
});
var staffSchema = new Schema ({
userId: { type: Schema.Types.ObjectId, ref: 'Account' },
role: { type: Number }
});
var adminSchema = new Schema ({
userId: { type: Schema.Types.ObjectId, ref: 'Account'}
})
var Places = mongoose.model('Places', PlaceSchema);
I tried to use this query, but without success.
Places.findOne({'_id' : placeId}).populate('staff.userId').exec(function(err, doc){
console.log(doc);
});
Polpulation is intended as a method for "pulling in" information from the related models in the collection. So rather than specifying a related field "directly", instead reference the related fields so the document appears to have all of those sub-documents embedded in the response:
Places.findOne({'_id' : placeId}).populate('staff','_id')
.exec(function(err, doc){
console.log(doc);
});
The second argument just returns the field that you want. So it "filters" the response.
There is more information on populate in the documentation.