I just need to update serviceActiveFlag status whenever i make an update api call.After an update api call,i can see a new document with empty vehicle array is created as shown below.
_id:59c76073c11d3929148f500f
vehicle:Array
_v:0
id field will override upon every put api call.
Can some one help me to resolve this issue?
schema
var localTransportSchema = new Schema({
name: { type: String, required: false, trim: true },
contact: {
addressLine1: { type: String, required: false },
serviceActiveFlag: { type: String, required: false, enum: ['Y', 'N'] },
},
vehicle: [{
vehicleType:{ type: String, required: false, enum: ['sedan', 'hatchback', 'suv', 'mpv', 'luxury'] },
}]
});
module.exports.accomodationModel = mongoose.model(collection, localTransportSchema);
controller
var updates = {
$set: {
"contact.addressLine1": req.body['addressLine1'],
"contact.serviceActiveFlag": req.body['serviceActiveFlag']
}
};
transportModel.findOneAndUpdate({ "name": req.body['providerName']},
updates, { returnOriginal: false, upsert: false }, function (err, doc) {
if (err) {
logger.error("Error while updating record : - " + err.message);
return res.status(409).json({
"Message": "Error while updating transport details for provider " + req.body['providerName'] + " in transport details table"
});
} else if (doc === null) {
logger.error("Error while updating record in transport details : - unable to update database");
return res.status(409).json({
"Message": "Error while updating transport details for provider " + req.body['providerName'] + " due to " + err.message
});
}
});
dbModel.findOneAndUpdate() of mongoose insert a new document only when your filter query(where claus) failed to find the existing document i.e there is no matching document exist in your collection.
So mongoose will insert the new document to the collection. This works similar to upsert:true of update()
Ref :Official docs about findOneAndUpdate
Related
I have a user and a premium schema. The premium one is embedded in user.
const premiumSchema = new mongoose.Schema(
{
subscriptionID: {
type: String,
required: true,
},
guild: {
type: Object,
default: {},
},
payment_id: {
type: String,
required: true,
},
expiry: {
type: Date,
require: true,
},
reminded: {
type: Boolean,
default: false,
},
},
{ collection: "premium" }
);
const userSchema = new mongoose.Schema({
discordId: {
type: String,
required: true,
},
accessToken: {
type: String,
required: true,
},
premium: {
type: [premiumSchema],
required: false,
},
});
I am trying to update a value of my premium collection by:
const user = await User.findOne({
"premium._id": new ObjectId(req.body.premiumId),
});
const premium = user.premium.id(new ObjectId(req.body.premiumId));
premium.reminded = true;
await user.save();
The Problem is that it updates the reminded attribute in my user.premium array but doesn't update it in the premium collection itself. Is there anything I am doing wrong?
You can use findOneAndUpdate method and positional operator to directly update your user.
Positional operator $ allows you to iterate through the array and update only the corresponding subdocument
const savedUser = await User.findOneAndUpdate(
{_id: new ObjectId(req.body.premiumId)},
{$set: {'premium.$.reminded': true}}
);
See doc: https://docs.mongodb.com/manual/reference/operator/update/positional/
This way you can update the subdocument within the User collection, but the value in the Premium collection will not be updated.
This is because when you define the premium property within the Users collection you are telling mongoose (and mongodb) to save the object within the user collection itself.
In this case there are no references between the two collections: the data will be saved only in the user collection, intended as subdocuments.
You are just defining schema for child won't create a separate collection for the children in the database instead you will embed the whole child document in the parent (user).
Example data:
user1: {
discordId: { 'abc' },
accessToken: { 'token' },
premium: {
subscriptionID: { 'idSubscription' }
guild: { },
payment_id: { 'idPayment' },
expiry: { '2021-07-31T20:41:19.618+00:00' },
reminded: { true }
},
});
The two User and Premium collections remain completely separate.
If you want to upgrade the Premium collection as well, you can do it using two different calls, one for User and one for Premium.
I am having a problem with the user model that I'm using with Mongoose and MongoDB to create each profile in my database. It works fine to post one user, but throws the following error if I logout and try again:
{
"name": "MongoError",
"message": "E11000 duplicate key error collection: CourtAPIDev.users index: trackers.case_id_1 dup key: { : null }",
"driver": true,
"index": 0,
"code": 11000,
"errmsg": "E11000 duplicate key error collection: CourtAPIDev.users index: trackers.case_id_1 dup key: { : null }"
}
According to mongoose documentation: If there is more than one document (a second user) without a value for the indexed field or is missing the indexed field, the index build will fail with a duplicate key error. I don't know how to set this _id property for the trackers property –– I thought it generated automatically!
Here's the trackers part of my Schema. And the relevant case_id property, which seems to be throwing the "null" error.
The whole repository can be found on my Github here, but the likely problem spots are the ones I highlighted, I think. Here's the github link: https://github.com/KingOfCramers/node_login_with_trackers
user model:
const UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
trim: true,
minLength: 1,
unique: true,
validate: {
validator: (value) => {
return validator.isEmail(value);
},
message: '{VALUE} is not a valid email'
}
},
password: {
type: String,
required: true,
minlength: 6
},
tokens: [{
access: {
type: String,
required: true
},
token: {
type: String,
required: true
}
}],
trackers: {
tweets: [TwitterSchema],
legislation: [LegislationSchema],
court_cases: [CourtCaseSchema]
},
frequency: [EmailSchema]
});
Express route:
app.post("/users", (req,res) => {
var body = _.pick(req.body, ['email', 'password']);
body.frequency = {
alert_time: new Date(),
email: req.body.email
}
var user = new User(body);
user.save().then(() => {
return user.generateAuthToken();
}).then((token) => {
res.header("x-auth", token);
res.send(user);
}).catch((e) => {
res.status(400).send(e);
});
});
Test (mocha):
it("Should post a new user", (done) => {
var email = "uniqueemail#example.com"
var password = "9webipasd"
supertest(app)
.post("/users") // Post request to the /todos URL
.send({
email,
password
})
.expect(200)
.expect((res) => {
expect(res.headers).toIncludeKey('x-auth')
expect(res.body._id).toExist();
expect(res.body.email).toBe(email);
})
.end((err) => {
if(err){
return done(err);
}
User.findOne({email}).then((user) => {
expect(user).toExist();
expect(user.password).toNotBe(password);
done();
}).catch((e) => done(e));
});
});
My guess is that there is an index on CourtCaseSchema.case_id which does not allow duplicates.
I think you could check (in a mongo shell) that with CourtAPIDev.court_cases.getIndexes() (I think your db is named CourtAPIDev and the collection is named court_cases but I am not sure about that).
Also if you clean the test db after each run, that would explain why the tests are passing, since there is no more than one user.
Turns out, it was to do with my mongodb database, not any of my code. After searching around online, I found that if I logged into the mongo shell and then dropped all indexes from the users collection, it solved my problem. Could someone explain why this was causing my program to crash? I think it may have to do with an old user model, but I don't really understand. Thanks!
Even if you have all of your keys as unique=False, you may still get E11000 duplicate key error. So in that case, just follow these steps and check if your error is resolved.
Delete all documents from the collection (e.g. db.collection_name.deleteMany({}))
Drop the COLLECTION (NOT THE DATABASE) (e.g db.collection_name.drop())
Cheers !!
I am currently working on a project and I am stuck with inserting an item into an array/object in the database. What I am trying to do is to add the id of a 'upvoted' post to an array/list in the 'User' Collection, however, I cannot seem to get it to work.
The code for my schemas is as follows:
// this is a child scheme/sub-document
var uvpSchema = new Schema();
uvpSchema.add({
post: String
});
var dvpSchema = new Schema();
dvpSchema.add({
post: String
});
//main schema
var userSchema = new Schema({
firstname: { type: String, required: true },
lastname: { type: String, required: true },
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
upVotedPosts: [uvpSchema],
downVotedPosts: [dvpSchema],
created_at: Date,
});
And here is the code in my 'routes.js' to insert the id of the post into the array:
var newPush = {
post: postID // postID is a variable that I have already defined
};
User.findOneAndUpdate({username: req.session.user}, {$push: {upVotedPosts: newPush}}, {upsert: true, save: true}, (err, user) => {
if (err) console.log(err);
user.upVotedPosts.push(newPush);
User.save;
res.redirect(req.get('referer'));
console.log(user.upVotedPosts);
});
The error I receive in my terminal is:
{ _id: 595f68b5fadd49105813f8a4 },{ _id: 595f693d3c2c21189004b0a7 },{ _id: 595f70a2df80e0252894551b }
events.js:163
throw er; // Unhandled 'error' event
^
Thanks in advance ;-)
Route.js
User.findOneAndUpdate({username: req.session.user}, {$push: {upVotedPosts: newPush}}, {upsert: true, save: true}, (err, user) => {
if (err) console.log(err);
user.upVotedPosts.push(newPush);
User.save;
res.redirect(req.get('referer'));
console.log(user.upVotedPosts);
});
You dont need to explicitly push, since you pushed using findOneandUpdate - $push
Refer here
Secondly , its
user.save()
and not
User.save
First of all, I'd like to thank everyone's' help ;-)
I finally managed to get it partially working! My problem was that my functions were running asynchronously, causing some problems. I solved this by adding callback functions to each mongoose function.
However, the same error is still being returned, causing the server to crash. Everything else works; the new item is added to the array.
Is there anyway to ignore the error so that the server doesn't crash?
I am using sequelize in my application. I have postgres as underlying database.
But when I tried to save instances I got following error
[error: missing dimension value]
I have the following model
module.exports = function(sequelize, DataTypes) {
var Mymodel = sequelize.define('Mymodel', {
id: {type : DataTypes.INTEGER, autoIncrement : true, primaryKey: true},
title: {
type: DataTypes.STRING(128),
validate: {
notNull: true,
notEmpty: true
}
},
tags: DataTypes.ARRAY(DataTypes.TEXT)
});
return Mymodel;
}
I am sending http post request as
{
"title":"Test challenge",
"tags" : "['JAVA','REST','API']"
}
I am saving object like this
Mymodel.create(model).success(function(model) {
callback(null, challenge);
}).error(function(err) {
callback(err, null);
});
I tried sending over your model object as you stated and did get the error SequelizeValidationError: "['JAVA','REST','API']" is not a valid array. Perhaps you got a different error on an older version of Sequelize. Then, I made sure the tags value was a JavaScript array instead of a string and it worked.
Mymodel.create({
title: 'Test challenge',
tags: ['JAVA','REST','API']
}).then(function() {});
I have an embedded document that needs to be updated. I have managed to get everything working except for one scenario: I am unable to get an embedded document with a nested hierarchy to get updated. Here is an example of what I'm attempting to do:
console.log('Phone type: ' + req.body.phone.type); // prints, e.g., 'Phone type: Work'
console.log('Phone #: ' + req.body.phone.number); // prints, e.g., 'Phone #: 555-555-5555'
var updateData = {
"user.$.contact_info": {
email: req.body.email,
phone: {
type: req.body.phone.type,
number: req.body.phone.number
}
}
};
Group.update(
{ "user._id" : req.params.user_id },
{ $push : updateData },
function(err,data) {
console.log('Success!'); // I see the "Success!" message every time I save a record
}
);
Schema:
var contactInfoSchema = mongoose.Schema({
created : {
type: Date,
default: Date.now
},
email : String
phone: {
type: String,
number: String
}
});
var userSchema = mongoose.Schema({
created : {
type: Date,
default: Date.now
},
contact_info : [contactInfoSchema]
});
var GroupSchema = mongoose.Schema({
created : {
type: Date,
default: Date.now
},
users : [userSchema]
});
What I find is that I can create records, but only the email address is stored, not the phone information. When inspecting the console I can see that the phone type and phone number info is being sent, but it just isn't updating in the database. What am I doing wrong?
The problem in in the "contactInfoSchema" with the use of the "type" keyword. You need this:
var contactInfoSchema = mongoose.Schema({
created : {
type: Date,
default: Date.now
},
email : String
phone: {
"type": { "type": String },
number: String
}
});
So basically mongoose is confused since you tried to call a "sub-document" field "type", and it thinks that is the data "type" for the field "phone". Declared as above all works fine.