I want to add a list of users in DB if they do not exist in DB and skip for the ones which already exists, for this, I am using writeMany operation with updateOne and upsert set as true. But it gives me StrictModeError.
Here is the function which creates the insertMany
const bulkWriteData = blacklistData.map(value => {
return {
updateOne : {
upsert: true,
filter : {
email : value
},
update : {
$set : {
_id : mongoose.Types.ObjectId(),
status : STATUS.BLOCKED,
createdAt : new Date(),
updatedAt : new Date()
}
}
}
}
})
await EmailUsers.bulkWrite(bulkWriteData)
Here is the EmailUsers Model
const mongoose = require('../config/connection')
const Schema = mongoose.Schema
const validator = require('../utils/validator.util')
const uniqueValidator = require('mongoose-unique-validator')
const EmailUsers = new Schema({
email: {
type: String,
required: true,
validate: validator.mongooseEmailValidator,
unique: true,
},
status: {
type: String,
enum: ['active', 'bounced'],
required: true,
default: 'active',
},
createdAt: {
type: Date,
required: true,
default: () => new Date(),
},
updatedAt: {
type: Date,
required: true,
default: () => new Date(),
},
bounceResponse: [
{
type: Object,
required: false,
},
],
})
EmailUsers.index({ email: 1, status: 1 })
EmailUsers.plugin(uniqueValidator, { type: 'mongoose-unique-validator' })
module.exports = mongoose.model('email_users', EmailUsers)
This is the validator used for email
const mongooseEmailValidator = validate({
validator: 'matches',
arguments: constants.regex.email,
message: 'Email should be a valid email address',
})
Here is the array which was sent to bulkwrite
[{
updateOne : {
upsert : true,
filter : { email: 'test#gmail.com' },
update : {
'$set': {
_id: 607ec7fd009fc824c5c34b5d,
status: 'blocked',
createdAt: 2021-04-20T12:24:29.693Z,
updatedAt: 2021-04-20T12:24:29.693Z
}
}
}
}]
Here is the error
error: Path "email" is not in schema, strict mode is `true`, and upsert is `true`. {"trace":"StrictModeError: Path \"email\" is not in schema, strict mode is `true`, and upsert is `true`.\n at cast
This doesn't make sense as I do have email in the schema
This actually updates the DB with the data and then throws the error.
What could be the possible solution?
Related
I have tried so many times to add new field to the existing MongoDB document but I failed. I tried following code to do the job but nothing happened.
Here is the User model.
const UserSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
},
{ timestamps: true }
);
Here is the code to add new field to the document.
const updateDocument = async () => {
const updatedUser = await User.findOneAndUpdate(
{ _id: "63eb30f466127f7a0f7a9b32" },
{
$set: { lastName: "syed" },
}
);
console.log(updatedUser);
};
updateDocument();
NOTE 1: lastName field does not exist in the MongoDB document and in the UserSchema. I want to add that field to the MongoDB document.
NOTE 2: The same code works when I update the existing field inside the document but it does not work when adding new field.
You need to pass strict:false as an option to findOneAndUpdate.
According to the mongoose doc:
The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.
const updatedUser = await User.findOneAndUpdate(
{ _id: "63eb30f466127f7a0f7a9b32" },
{
$set: { lastName: "syed" },
},
{ strict: false }
);
An alternative way is to pass this parameter when you defined the schema:
const UserSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
},
{ timestamps: true, strict: false }
);
I have a mongoose model where one of the fields is an array of dates and I need to query the collection to find any document that has a date between the 7 past days inside that array, but when I try to use $gt or $gte it doesn't return me the documents, even if exists (I have checked if the documents exist).
Here it is an example of the object
It shouldn't return me objects with more than 7 days past.
Here is the code that I'm using:
const { subDays } = require("date-fns");
const mongoose = require("mongoose");
const Journey = require("./models/Journey");
const url = "my-db-url";
mongoose.set("useNewUrlParser", true);
mongoose.set("useUnifiedTopology", true);
mongoose.set("useCreateIndex", true);
mongoose.set("useFindAndModify", false);
mongoose.connect(url, (err) => {
if (err) throw err;
console.log("Mongoose connected");
});
Journey.find({
hospital: "5e6fc0d98db5810012aeb8fe",
active: false,
timestampStart: {
$gte: subDays(new Date(), 7)
}
})
.lean()
.exec((err, journeys) => {
if (err) throw err;
console.log(journeys[0]);
});
The Journey model:
const { Schema, model } = require("mongoose");
const JourneySchema = new Schema(
{
tag: {
type: Schema.Types.ObjectId,
required: true,
ref: "Tag",
},
patient: {
type: Schema.Types.ObjectId,
required: true,
ref: "Patient",
},
hospital: {
type: Schema.Types.ObjectId,
required: true,
ref: "Hospital",
},
department: {
type: [String],
required: true,
},
timestampStart: {
type: [Date],
required: true,
},
timestampEnd: {
type: [Date],
required: true,
},
active: {
type: Boolean,
default: true,
},
rssi: {
type: [String],
required: true,
},
},
{
timestamps: true,
}
);
module.exports = model("Journey", JourneySchema);
Can anyone help me build this filter?
The date query seems to working just fine. I think the problem would be with the hospital, and active key. In the sample object that you have provided, both are missing. Can you check it by removing those keys in the query, or by adding them in the collection.
I have two models
1.PageType Model
module.exports = (mongoose) => {
const pageTypeSchema = new mongoose.Schema({
title: {
type: String,
key: {
type: String,
required: true,
},
}, {
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
});
return mongoose.model('PageType', pageTypeSchema);
};
WorkFlow Model
module.exports = (mongoose) => {
const workFlowSchema = new mongoose.Schema({
title: {
type: String,
default: null,
},
key: {
type: String,
default: null,
},
level: {
type: Number,
required: true,
},
page_type_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'PageType',
},
}, {
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
});
return mongoose.model('WorkFlow', workFlowSchema);
};
But when I try to use populate it throws Schema hasn't been registered for model PageType
async getFlowById(flowId) {
const result = await this.workFlow.findById(flowId).populate('page_type_id').exec();
return result;
}
Can anyone please help me with this??
In app.js the models are included before routes also PageType model is also declared before WorkFlow model
You typed wrong collection name. Collection name is Workflow and you are trying to findById at workflow. So i think Workflow should be there. Just try with that.
Im under the assumption that adding unique: true to a field would stop from saving to the database using the same value. But im still allowed to do it.
"mongoose": "^5.4.19",
const SessionSchema = new Schema({
jobId: {
type: String,
required: false,
unique: true,
index: true,
},
productId: {
type: String,
required: true,
},
status: {
type: String,
default: "Pending",
},
mode: {
type: String,
default: "authentication",
},
result: {
type: Schema.Types.Mixed,
},
requests: [RequestSchema],
callback_at: {
type: Date,
},
}, {
timestamps: { createdAt: "created_at", updatedAt: "updated_at" },
});
I have already tried deleting and recreating the collection. See the image below i can create new session with the same jobId being 1.
public store = async (req: Request, res: Response): Promise<any> => {
const input = req.body;
let session = new Session({
productId: input.productId,
jobId: input.jobId,
});
try {
session = await session.save();
const response = {
success: true,
status: 201,
data: { session },
message: "SESSION CREATED",
};
return res.status(response.status).json(response);
} catch (err) {
const response = {
success: false,
status: 500,
errors: [],
message: "UNEXPECTED SESSION ERROR",
};
if (err.code === 11000) {
response.errors.push({
code: 11000,
message: "Duplicate key error jobId",
});
}
return res.status(response.status).json(response);
}
db.sessions.getIndex();
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "myDB.sessions"
}
]
You have to understand that unique is an index configuration option in your schema.
For instance, if the users collection doesn't have a unique index on userName, then you need to wait for the index to build before you start relying on it.
const user = new mongoose.Schema({
userName: { type: 'String', unique: true },
});
const User = db.model('User', user);
const doc = new User({
userName: 'Bob'
});
return User.init() // `User.init()` returns a promise that is fulfilled when all indexes are done
.then(() => User.create(doc))
.then(() => User.create({ userName: 'Bob' }));
}
I was not using unique properly: https://mongoosejs.com/docs/validation.html#the-unique-option-is-not-a-validator
Need to wait until the indexes are built before relying on unique to be a validator.
I changed my mongoose connect options to look like the following
options: {
useNewUrlParser: true,
useCreateIndex: true,
autoIndex: true,
},
I;m not sure if its the most appropriate solution, but its the one ive gone with for now.
I have this problem. Basically, I have 2 schemas - a User schema and a Document schema. The Document schema has an owner which references the _id field of documents in the User collection.
The problem is that I am still able to save documents in the Document collection with owner ids that do not exist in the User collection which should not be so.
Here is my User schema and Document schema respectively
const UserSchema = new Schema({
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
email: {
type: String,
validate: [{ validator: value => isEmail(value), msg: 'Invalid email.'
}],
unique: true,
required: true,
},
password: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
default: false,
},
}, {
timestamps: true,
});
const User = mongoose.model('User', UserSchema);
And the Document Schema
const DocumentSchema = new Schema({
title: {
type: String,
required: true,
},
text: {
type: String,
},
access: {
type: String,
enum: ['public', 'private'],
default: 'public',
},
owner: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
}, {
timestamps: true,
});
const Document = mongoose.model('Document', DocumentSchema);
Any help will be appreciated thanks.
For that situation you can add pre save function in your Document schema that will call before save your Document.
const DocumentSchema = new Schema({
// ...
}, {
timestamps: true,
});
DocumentSchema .pre("save",function(next) {
var self = this;
if (self.owner) {
mongoose.models['User'].findOne({_id : self.owner }, function(err, existUser){
if(err){
return next(false, err);
}
if(!existUser)
return next(false, "Invalid user reference");
else
return next(true);
});
} else {
next(false, "Owner is required");
}
});
const Document = mongoose.model('Document', DocumentSchema);