create a schema for nested objects in mongo db - node.js

I have data that looks like this:
{
name:'name'
email:'email'
password:'pass'
role:{checked: {'1' : true, '2': true ... any number of key value pairs}}}
}
How do I create mongoose schema for this kind of data
?
var CustomUserSchema = new Schema({
name: String,
email: { type: String, lowercase: true },
role: {
checked: { type: Number, type: boolean } //I need to define something like this here probably
},
hashedPassword: String,
provider: String,
salt: String
});
How do I define the schema for this? Basically I am storing the checkbox values in role field.
Checkbox fields have their ng model set to user.role.checked[$index]

Related

object as property mongoose mongodb

I need a property in a mongoose model that is as following:
customRanks should have different keys and different values for each key
const config = new Schema({
id: { type: String, required: true, unique: true },
//...other property
customRanks: Object,
});
You can defined custome rank schema and use this as a object if you want to save data in specific format for customRanks fields
const customRanksSchema = new Schema({
key1: { type: Number, default: 0 },
key2: { type: Number, default: 0 },
key3: { type: String, default: '' }
})
If you want static schema and have specific fields for your custome rank object
// if you want to save customeRanks as array of object
customRanks: [{ type: customRanksSchema }],
// if you want to save custom rank as a object
customRanks: customRanksSchema
If you are looking for validation without key specifically. Then you may need to validate data before insert/create/update using javascript.

How to update an array inside of a mongoose schema?

How to update an array inside a mongoose schema with updateOne?
I have one model on my Node.Js application that I've made with mongoose schema.
One of the fields of my schema is an array:
guestsNames: []
I'm already able to save items inside of this array but I didn't find a way to update the items inside of it.
Here is my whole schema:
const screenImageSchema = mongoose.Schema({
company: {
type: String,
require: true,
trim: true
},
guestsNames: [],
imageName: {
type: String,
require: true
},
defaultImageName: {
type: String,
require: true
},
date: {
type: String,
default: Date.now,
require: true
},
activated: {
type: String,
default: 'Enabled'
},
wsType: {
type: String,
default: 'Image'
}
}, {timestamps: true});
...and my updateOne method:
screenImageSchema.methods.updateOne = function(id, screenImage) {
const updatedScreenImage = {
company: screenImage.company,
guestsNames: screenImage.guests,
imageName: screenImage.imageName,
defaultImageName: screenImage.defaultImageName,
date: screenImage.date,
activated: screenImage.activated,
wsType: screenImage.wsType
}
ScreenImage.updateOne(id, updatedScreenImage, {new: true});
}
The 'screenImage' parameter passed to the function is an object with all information that I need, including an array with all strings for guestsNames (I've already checked if the parameters are being passed correctly to the object and they are). All fields are being updated with this piece of code except the guestsNames field. What am I doing wrong and how can I make the guestsNames array be updated correctly?
Cheers.
You can update directly your array like this
ScreenImage.updateOne(id, { $set : { guestNames : newArray }})
You need to use $set to replace the value of a field, see this mongoDB $set
try this if it works
screenImageSchema.methods.updateOne = function(id, screenImage) {
const updatedScreenImage = {
company: screenImage.company,
guestsNames[0]: screenImage.guests,
imageName: screenImage.imageName,
defaultImageName: screenImage.defaultImageName,
date: screenImage.date,
activated: screenImage.activated,
wsType: screenImage.wsType
}
ScreenImage.updateOne(id, updatedScreenImage, {new: true});
}

Insert a document with mongoose without initialize the model with empty attributes

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!

Mongoose: Add validators on the fly on some parameters depending on queries

I am new to Mongoose and would like to know if it is possible to add validators on the fly on some parameters depending on queries. I have for example a schema like below:
var user = new Schema({
name: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
city: { type: String },
country: { type: String }
});
For a simple registration i force users giving the name, the email and the password. The Schema on top is OK. Now later I would like to force users giving the city and the country. Is it possible for example to update a user's document with the parameters city and country on required? I am avoiding to duplicate user schema like below:
var userUpdate = new Schema({
name: { type: String },
email: { type: String },
password: { type: String },
city: { type: String, required: true },
country: { type: String, required: true }
});
What you would need to do in this case is have one Schema and make your required a function which allows null and String:
var user = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
city: {
type: String,
required: function() {
return typeof this.city === 'undefined' || (this.city != null && typeof this.city != 'string')
}
}
});
You can extract this and make it an outside function which then you can use for county etc.
What this does is it makes the field required but also you can set null to it. In this way you can have it null in the beginning and then set it later on.
Here is the doc on required.
As far as I know, no, it is not possible.
Mongoose schema are set on collection, not on document.
you could have 2 mongoose model pointing to the same collection with different Schema, but it would effectively require to have duplicated Schema.
personnally, in your situation, I would create a single home-made schema like data structure and a function who, when feeded with the data structure, create the two version of the Schema.
by example :
const schemaStruct = {
base : {
name: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
city: { type: String },
country: { type: String }
}
addRequired : ["city", "country"]
}
function SchemaCreator(schemaStruct) {
const user = new Schema(schemaStruct.base)
const schemaCopy = Object.assign({}, schemaStruct.base)
schemaStruct.addRequired.forEach(key => {
schemaCopy[key].required = true;
})
const updateUser = new Schema(schemaCopy);
return [user, updateUser];
}

Validate subdocuments in Mongoose

I am using a Schema as a Subdocument in Mongoose, but I am not able to validate it in its fields.
That's what I have
var SubdocumentSchema = new Schema({
foo: {
type: String,
trim: true,
required: true
},
bar: {
type: String,
trim: true,
required: true
}
});
var MainDocumentSchema = new Schema({
name: {
type: String,
trim: true,
required: true
},
children: {
type : [ SubdocumentSchema.schema ],
validate: arrayFieldsCannotBeBlankValidation
}
});
I want to be sure that every field of the subdocument is not empty.
I found out that this is not possible to validate an Array with standard methods, so I wrote my custom validation function.
By now I have to manually check that all the fields are correct and not empty, but it looks to me like a not really scalable solution, so I was wondering if there was some native method to trigger the Subdocument validation from the MainDocument one.
In the definition of children, it should be [SubdocumentSchema], not [SubdocumentSchema.schema]:
var MainDocumentSchema = new Schema({
name: {
type: String,
trim: true,
required: true
},
children: {
type : [ SubdocumentSchema ],
validate: arrayFieldsCannotBeBlankValidation
}
});
SubdocumentSchema.schema evaluates to undefined so in your current code Mongoose doesn't have the necessary type information to validate the elements of children.

Resources