I'm working with a complex data structure in MongoDB and using mongoose
to handle the server-to-database communication.
In mongoose
I have a schema defined like this:
var mongoose = require('mongoose')
var Schema = mongoose.Schema;
const timePeriodSchema = new mongoose.Schema({
opensAt: {type: String, default: null},
closesAt: {type: String, default: null}
});
const daySchema = new mongoose.Schema({
closed: {type: Boolean, default: false},
hours: [timePeriodSchema]
});
const weekSchema = new mongoose.Schema({
monday: daySchema,
tuesday: daySchema,
wednesday: daySchema,
thursday: daySchema,
friday: daySchema,
saturday: daySchema,
sunday: daySchema,
});
const restaurantSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
required: false,
ref: 'User',
default: null
},
name: {
type: String,
required: true,
default: null
},
category: [String],
type: [String],
style: [String],
cuisine: [String],
customDescription: {
type: String,
required: false,
default: null
},
address: {
type: String,
required: true,
default: null
},
countryCode: {
type: String,
required: true,
default: null
},
services: [String],
photos: [Buffer],
openingHours: weekSchema,
phonePrefix: {
type: String,
required: true,
default: null
},
phoneNumber: {
type: String,
required: true,
default: null
},
website: {
type: String,
required: false,
default: null
},
reservationMethods: [String],
paymentMethods: [String],
createdAt: {
type: Date,
required: true,
default: Date.now,
}
});
module.exports = mongoose.model('Restaurant', restaurantSchema)
And I try to create a new Restaurant with the following code:
saveRestaurant: function(req, res){
Restaurant.findOne({
address: req.body.address
}, function(err, restaurant){
if(err) throw err;
if(restaurant){
return res.status(500).send({success: false, key: 'addressUsed', title: res.__('requestFailedTitle'), msg: res.__('restaurantSaveAlreadyExistsErrorMsg')});
}else{
User.findOne({
email: req.body.userEmail
}, function (err, user){
if(err){
throw err
}
if(user){
var restaurant = new Restaurant(req.body);
restaurant.userId = user._id;
restaurant.save(function(err, restaurant){
if(err) throw err;
});
return res.status(200).send({success: true, msg: res.__('saveSuccessResponse')});
}
});
}
});
}
And here is a sample of the req.body
that the server receives:
{
"userEmail": "example@gmail.com",
"name": "My Restaurant",
"category": [ "Café", "Pub" ],
"type": [ "Ethnic Restaurant", "Fine Dining Restaurant" ],
"style": [ "Elegant" ],
"cuisine": [ "Haute" ],
"customDescription": "This is a custom description",
"address": "Piazza di Spagna, Piazza di Spagna, Rome, Metropolitan City of Rome, Italy",
"countryCode": "IT",
"services": [ "Handicap", "Restroom" ],
"photos": [],
"openingHours": {
"Monday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]},
"Tuesday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]},
"Wednesday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]},
"Thursday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]},
"Friday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]},
"Saturday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]},
"Sunday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]}
},
"phonePrefix": "+39",
"phoneNumber": "1234567890",
"website": "asdfg.it",
"reservationMethods": [ "Phone" ],
"paymentMethods": [ "Cash", "Card" ]
}
The problem is that the restaurant created has all the fields set perfectly, except for the nested openingHours field.
In the openingHours
field only the _id
of an object is stored and nothing else.
It seems that mongoose
is not able to retrieve and populate the nested schemas.
However I have read that apparently it should be able to. Anyone have any idea of what I am doing wrong?
I don't want to use separate collections and link them via _id
as it would result in too many useless collections; I would like to have everything in the same collection.
Here below is a screenshot of what is actually saved in MongoDB:
Your definition of days in a schema and days in data are in different cases:
all small letters
const weekSchema = new mongoose.Schema({
monday: daySchema,
tuesday: daySchema,
wednesday: daySchema,
thursday: daySchema,
friday: daySchema,
saturday: daySchema,
sunday: daySchema,
});
and in data the first letter is capital:
"Monday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]},
"Tuesday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]},
"Wednesday": { "closed": true, "hours": [
{"opensAt": "11:00", "closesAt": "17:00"}
]},
...