Invalid Object Passes Schema Validation - node.js

In a meteor app I've been getting my feet wet with SimpleSchema lately. I've built the below mentioned pretty simple schema :-)
However, when I try to validate an invalidate entry (say one where entry.link.url ist not a valid URL or one where entry.link.project is undefined) against that schema via entrySchema.validate() the validation does not work properly, i.e. the invalid entry passes the validation whereas I would expect it to fail.
let entrySchema = new SimpleSchema({
userId: {
type: String,
optional: true
},
link: {
type: Object
},
'link.project': {
type: String //this validation does not work!
},
'link.url': {
type: SimpleSchema.RegEx.Url //this validation does not work!
}
});
Can anyone please tell me what I am doing wrong or what I am missing here?

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.

Mongoose post hook Type error in TypeScript

I am using mongoose and typescript, when I call updateOne() on the model I want to use
someSchema.post<Query>('updateOne', function(doc: IsomeDoc) {
console.log(this)
}
The problem is that this is of type Query if I suppress typescript checker and ignore as it give me an error:
Generic type 'Query<ResultType, DocType, THelpers>' requires between 2 and 3 type arguments.
This is my schema
const someSchema = new Schema(
{
_id: { type: String, required: true },
status: { type: String },
},
{ timestamps: true }
)
How can I get the correct type for this inside the function? After lots of searching there is barely any use of post hook with typescript and mongoose.
What is ResultType?
Edit:
After seeing #gregooroo's answer I was able to get past Query by making it Query<IsomeDoc, IsomeDoc> but it does not give me the correct type for this object.
For query middlewares you need to construct a Query type with a generic type of what this query should return
someSchema.post<Query<IsomeDoc, IsomeDoc>>('updateOne', function(doc) {
console.log(this)
}

How to Post Enum data in Postman with form-data type

I've tried searching Google but the answer is irrelevant, what I want to ask is how to Post enum data in Postman.
i currently work in node js with express framework, and i try to modeling my mongoose with multiple reference with enum
but, honestly i always fail when to hit the endpoints
this is my code
fieldBookedIDs: {
type: Schema.Types.ObjectId,
required: true,
// Instead of a hardcoded model name in `ref`, `refPath` means Mongoose
// will look at the `onModel` property to find the right model.
refPath: 'fieldBookedID'
},
fieldBookedID: {
type: String,
required: true,
enum: ['Player', 'Community']
},
{
the result is
"error": {
"message": "field validation failed: fieldBookedIDs: Cast to ObjectID failed for value \"{ fieldBookedID: [ '12234553fscdf', '15454asdasd' ] }\" at path \"fieldBookedIDs\", fieldBookedID: Path `fieldBookedID` is required."
}
}
thank you for helping :)
this is an image for my postman

findByIdAndUpdate throwing cast error when I try and update a property to null

Schema:
var SomeSchema = new Schema({
name: { type: String, required: true, unique: true },
description: { type: String, required: false }
},{
versionKey: false
}
);
// In this case the client did not pass me a description, which is ok cause this property is not required.
// Why would the update fail?
var update = {name: someName, description: someDescription};
findByIdAndUpdate(id, update, function(err, something) { ...
Here is the error, yup cannot cast null/undefined to a String but why try?
CastError: Cast to string failed for value "undefined" at path
"description"
The update is failing because, while you're setting description to not required, the update method will still look into the value of update.description if there is one defined in the update object. This is because, according to the docs:
The update field employs the same update operators or field: value
specifications to modify the selected document.
In any case, the simple way to solve this would be to check if the description value is being passed before inserting it into the update object.
var someDescription = req.body.args.description;
var update = {name: someName};
if(someDescription)
update['description'] = someDescription;
On a side note, nulls are not allowed, as stated here

Mongoose Changing Schema Format

We're rapidly developing an application that's using Mongoose, and our schema's are changing often. I can't seem to figure out the proper way to update a schema for existing documents, without blowing them away and completely re-recreating them from scratch.
I came across http://mongoosejs.com/docs/api.html#schema_Schema-add, which looks to be right. There's little to no documentation on how to actually implement this, making it very hard for someone who is new to MongoDB.
I simply want to add a new field called enabled. My schema definition is:
var sweepstakesSchema = new Schema({
client_id: {
type: Schema.Types.ObjectId,
ref: 'Client',
index: true
},
name: {
type: String,
default: 'Sweepstakes',
},
design: {
images: {
type: [],
default: []
},
elements: {
type: [],
default: []
}
},
enabled: {
type: Boolean,
default: false
},
schedule: {
start: {
type: Date,
default: Date.now
},
end: {
type: Date,
default: Date.now
}
},
submissions: {
type: Number,
default: 0
}
});
Considering your Mongoose model name as sweepstakesModel,
this code would add enabled field with boolean value false to all the pre-existing documents in your collection:
db.sweepstakesModel.find( { enabled : { $exists : false } } ).forEach(
function (doc) {
doc.enabled = false;
db.sweepstakesModel.save(doc);
}
)
There's nothing built into Mongoose regarding migrating existing documents to comply with a schema change. You need to do that in your own code, as needed. In a case like the new enabled field, it's probably cleanest to write your code so that it treats a missing enabled field as if it was set to false so you don't have to touch the existing docs.
As far as the schema change itself, you just update your Schema definition as you've shown, but changes like new fields with default values will only affect new documents going forward.
I was also searching for something like migrations, but didn't find it. As an alternative you could use defaults. If a key has a default and the key doesn't exist, it will use the default.
Mongoose Defaults
Default values are applied when the document skeleton is constructed. This means that if you create a new document (new MyModel) or if you find an existing document (MyModel.findById), both will have defaults provided that a certain key is missing.
I had the exact same issue, and found that using findOneAndUpdate() rather than calling save allowed us to update the schema file, without having to delete all the old documents first.
I can post a code snippet if requested.
You might use mongo shell to update the existing documents in a specific collection
db.SweeptakesModel.update({}, {$set: {"enabled": false}}, {upsert:false, multi:true})
I had a similar requirement of having to add to an existing schema when building an app with Node, and only found this (long ago posted) query to help.
The schema I added to by introducing the line in the original description of the schema and then running something similar to the following line, just the once, to update existing records:
myModelObject.updateMany( { enabled : { $exists : false } }, { enabled : false } )
'updateMany' being the function I wanted to mention here.
just addition to what Vickar was suggesting, here Mongoose Example written on Javascript (Nodejs):
const mongoose = require('mongoose');
const SweeptakesModel = mongoose.model(Constants.SWEEPTAKES,sweepstakesSchema);
SweeptakesModel.find( { enabled : { $exists : false } }).then(
function(doc){
doc.enabled = false;
doc.save();
}
)

Resources