Mongoose Schema enum validation on array of strings - node.js

The enum validation works when it's a single String:
var songSchema = new Schema({
vocalRange: {
type: String,
enum: ["Soprano", "Mezzo-soprano", "Contralto", "Alto", "Tenor", "Baritone", "Bass"],
}
})
Trying to POST anything but what's in the enum returns a validation error through mongoose.
However, the following:
var songSchema = new Schema({
vocalRange: {
type: [String], // this is what changed
enum: ["Soprano", "Mezzo-soprano", "Contralto", "Alto", "Tenor", "Baritone", "Bass"],
}
})
Allows me to POST anything for vocalRange without any kind of validation. What's going on? And why doesn't the validation work for an array of strings like it does for a single string?

Answering from my comment:
vocalRange: [{ type: String }]
should work.

As of mongoose version 5.0.6 and higher, the OP issue now works!
vocalRange: {
type: [String], // this now works!
enum: ["Soprano", "Mezzo-soprano", "Contralto", "Alto", "Tenor", "Baritone", "Bass"],
}
Reference
https://github.com/Automattic/mongoose/issues/6204#issuecomment-374690551

Related

How to insert Array of objects in mongoDB?

I am very new to MONGO DB so please bear with me.I am having a problem my array of objects is not working properly .
Here is my schema
const playerSchema = new mongoose.Schema({
name: String,
stats :{
wins:Number,
losses:Number,
xp:Number
},
achievement:[
{
name:String,
date: String
}
] });
Here is my document
const fluffy = new playerModel({
"name":"nic raboy",
"stats":{
"wins":5,
"losses":10,
"xp":300
},
"achievements":[
{"name":"Massive XP","date" :"25-08-21"},
{"name":"instant loss","date":"24-08-21"}
]
});
however in mongodb atlas its only showing array...and i cant see the objects inside...
SCREENSHOT
Your schema is correct, it seems your input is wrong,
In schema definition you named it achievement, whereas in input document it is achievements. Correct this everything will work as you expected.
Explanation
The schema is expecting achievement and you inserted achievements, that is why it is shown as an empty array in the database. To avoids this kind of typos in the future, use the required flag.
const playerSchema = new mongoose.Schema({
name: String,
stats: {
wins: Number,
losses: Number,
xp: Number
},
achievements: [
{
name: {
type: String,
required : true,
},
date: {
type: String,
required : true, // required informs for missing fields
}
}
]
})
Refer this link for more on validation
You can use insertMany see the doc here.
Of course, a while loop should work find calling multiple times insertOne, though I advise you to use the insertMany() method.
If you're new to MongoDB, I strongly encourage you to have a look at MongoDB University's MongoDB basics course as well as the MongoDB for JavaScript Developers course.

How to use $push inside $set in mongoose?

I'm using express-restify-mongoose library to have rest endpoints agaist mongoose.
I have schema looks like this:
const BookSchema = new Schema(
{
name: { type: String },
items: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Book' }],
}
);
So I send http patch request: { name: 'blabla' } and it change the name as expect.
But when I want to add item to items array like { items: ["5dd138199f6ecb3990360328"] } its replace the entire object (with one 5dd138199f6ecb399036032d item).
After I digging in the source code I see here the function uses findOneAndUpdate and $set.
So my question is there is any way to use $push or any function/property in the $set value?
I can't add to this library, but maybe there is any workaround solution here?
I think the closest solution in mongoose is to use Set Elements in Arrays:
"items.1": "5dd138199f6ecb3990360355"
Which will add to array, but you have to pass the position.

Mongoose Schema: object with any property name possible?

I would like to define a Mongoose Schema which accepts any property name in connection with a String as its value. What I am looking for is something like the following (Without having first to write any possible property name):
var schema = new Schema({
name: String,
someStrings: {
string1: String,
string2: String,
...
stringN: String
}
});
I know I could simply use Schema.Types.Mixed, but that would make it possible to use arrays or other types inside. Furthermore would Mongoose lose the ability to auto detect and save changes on this property.
var schema = new Schema({
name: String,
someStrings: Schema.Types.Mixed
});
I just want to have an Object (someString), which only consists of an arbitrary count of name to value String mappings with any name possible.
Is something like this even possible in mongoose?
var schema = new Schema({
name: String,
strings: {
type: Object,
default: {
string1: String,
string2: String,
...
stringN: String
}
}
});

How to get enum values from mongoose schema using virtual method?

I'm having difficulty getting enum values from my Mongoose schema using a virtual method on that same schema.
The property I'm trying to access in the schema is defined as follows:
, roles: {
type: [{
type: String
, enum: ['user', 'admin']
}]
, default: ['user']
}
The following is my virtual method I'm using to grab the enum values:
// Returns an array of all possible role enum values
UserSchema.virtual('possibleRoles').get(function() {
return this.schema.path('roles').caster.enumValues;
});
This works, however other examples I found online went about it in a different way. An example of this is here: Access the list of valid values for an Enum field in a Mongoose.js Schema
Is my method for accessing enums on a property dirty or incorrect? Is there a cleaner way I could write this?
This is clean and easy way.
var possibleRoles = ['user', 'admin'];
var UserSchema = new Schema({
roles: {
type: [{type: String, enum: possibleRoles}],
default: ['user']
}
});
UserSchema.virtual('possibleRoles').get(function () {
return possibleRoles;
});
remove the caster part, i don't know why that is there:
return this.schema.path('roles').enumValues;
that should work without any other issues

Mongoose variable key name

I have a mongo object and wish to access it via mongoose for my web app. The schema I've defined has an Object storing user ids and a 3-level value (yes, maybe or no).
e.g.
"user_info": {
"<id_value_1>": "y",
"<id_value_2>": "n"
}
The id_value_*s above are the users session ids so a long string of random characters. How can I create a mongoose Schema for this?
Would user_info: {String, String} work?
I could restructure it so that the user_info is an array of objects { "sessionid": "<value>", "value: "y"}, which would be ok, is this the best option?
You'll be better off if you avoid dynamic keys in your schema and go with your second idea of:
user_info: [{sessionid: String, value: String}]
You can use the $ positional operator to update individual user_info array elements by sessionid.
You may try with Schema Type Mixed like this way
var user = new Schema({
info: [Schema.Types.Mixed]
});
user.info = { any: { thing: 'i want' } };
user.markModified('info');
You can read more about it here
After testing the above, I found that defining the schema as user_info: { String: String } is a valid way to do this (option 1 specified in the question).
You may define objects and arrays in your schema. You may even combine them. For example, this is an array of objects:
var user = new Schema({
foo: [ {
address: {type: String},
email: {type: String, unique: true}
}],
bar: [ "simple", "array" ]
});

Resources