I am trying to add a number to an item in a document in MongoDB
I have this code:
const schema = require('./commands/serverstats')
const data = await schema.findOne({ Main:'Main' })
data.TotalBobuxGiven += Number(args[0])
data.TotalRobuxGiven += Number(args[1])
await data.save()
message.reply(`Done`)
console.log('done')
It doesn't return done or it doesn't add the data properly. The schema is correct, and I am using the correct variables. There are no errors. What am I doing wrong?
Query
try update, and 1 query, making the update faster atomic and safe
*i dont use mongoose, but you dont need find and save, update is the right way to do it
Test code here
db.collection.update({
Main: "Main"
},
{
$inc: {
"TotalBobuxGiven": Number(args[0]),
"TotalRobuxGiven": Number(args[1])
}
})
Related
Hello I have json data like that:
{
"_id":ObjectId('5dfe907f80580559fedcc9b1'),
"companyMail":"mail#gmail.com"
"workers":[
{
"name":name,
"surName":surname,
"mail":"mail2#gmail.com",
"password":"password",
"companyMail":"mail#gmail.com",
}
]
}
And I want to get an worker from workers:
{
"name":name,
"surName":surname,
"mail":"mail2#gmail.com",
"password":"password",
"companyMail":"mail#gmail.com",
}
I'm writing this query:
collection.findOne({
'companyMail':"mail#gmail.com",
'workers.mail':"mail2#gmail.com",
});
But it gives me whole of data. I only want to get worker which I search. How can I do that with Mongo Dart.
https://pub.dev/packages/mongo_dart
I found the solution. We should use aggregation but we should add some specific query to get one result. In dart mongo, we can use Filter object to add. Like that:
final pipeline = AggregationPipelineBuilder()
.addStage(Match(where.eq('companyMail', companyMail).map['\$query']))
.addStage(Match(where.eq('customers.mail', customerMail).map['\$query']))
.addStage(Project({
"_id": 0, //You can use as:'customer' instead of this keyword.
"customers": Filter(input: '\$customers',cond: {'\$eq':["\$\$this.mail",customerMail]}).build(),
}))
.build();
final result = await DbCollection(_db, 'Companies')
.aggregateToStream(pipeline)
.toList();
mongo-dart API driver is very bad and there is no good documentation whereas mongo-node.js API driver is very good and has very good documentation, so better to do server side with node, for example in node your problem will solve by one line code:
collection.find(
{
'companyMail':"mail#gmail.com",
'workers.mail':"mail2#gmail.com",
}).project({
'_id':0, 'workers':1
});
Pass options to project the workers field only
db.company.findOne(
{
'companyMail':"mail#gmail.com",
'workers.mail':"mail2#gmail.com",
},
{
"workers":1,
_id:0
}
);
In mongo-dart , looking at their api, you can use aggregation which is as follows
final pipeline = AggregationPipelineBuilder()
.addStage(Match(where.eq('companyMail','mail#gmail.com')))
.addStage(Project({
'_id': 0,
"workers":1,
})).build())
final result =
await DbCollection(db, 'company')
.aggregateToStream(pipeline).toList();
// result[0] should give you one worker
I'm trying to check that an update command accomplished but when I check for the nModified I'm getting 0 although I do see that the field value changes from one value to another (not kept the same value).
static async updateProfile(username, profileData) {
const usersCollection = db.dbConnection.collection(dbConfig.collectionNames.users);
const updateRes = await usersCollection.update({email: username},
{"$set": {
firstName: profileData.firstName,
lastName: profileData.lastName,
payment: profileData.payment,
}
});
return updateRes.result.nModified > 0;
}
Is there another way to verify the update?
One of the way by findAndModify method:
You can easily compare whole new object and verify each key.
db.getCollection('usertests').findAndModify({
query: {"email":"xxx#xxx.com"},
update: {name: "HHH", "email":"xxx#xxx.com"},
new: true
})
new: true is responsible to return whole updated document. If fail to update it will return null.
Take care here to pass the whole document while update.
update() only return a number of the documents that were successfully updated. So, your logic to check if updated successfully or not is also valid.
I have my Model as
var Model = {"name":String,"email":String,"notes":[{"time":Date,"title":String,"description":String}]
And I want to find document based on the email, and then add a note to the array. And then save it back.
What I tried is,
var updatedNote = {};
Model.findOne({'email':'test#test.com'},function(err, note){
for(var property in note._doc){
if(note._doc.hasOwnProperty(property)){
updatedNote[property] = note._doc[property];
};
}
updatedNote.notes.push(newNote);
note._doc = updatedNote;
note.save(function(err){
if(err){
console.log(error);
}
else {
res.redirect('/notes');
}
})
});
But it is throwing error as "Object does not have save method". I don't want to use findByIdAndUpdate() as i am leaving this responsibility of generating id on mongo.
I don't understand what most of that code is doing. If I wanted to add a note to the document (I'm assuming newNote is defined elsewhere), I'd just do:
Model.findOne({'email':'test#test.com'},function(err, note){
note.notes.push(newNote);
note.save(function(err){});
});
I have mongoosastic setup within a MEAN stack program. Everything works correctly except when I delete a document from mongodb it is not deleted in the elasticsearch index. So every time I do a search that includes delete items, the deleted item is returned but is null when it is hydrated. Does mongoosastic handle deleting from the ES index? Do I have to program an index refresh?
var mongoose = require('mongoose');
var mongoosastic = require("mongoosastic");
var Schema = mongoose.Schema;
var quantumSchema = new mongoose.Schema({
note: {
type: String,
require: true,
es_indexed: true
}
});
quantumSchema.plugin(mongoosastic);
var Quantum = mongoose.model('Quantum', quantumSchema);
Quantum.createMapping(function(err, mapping){
if(err){
console.log('error creating mapping (you can safely ignore this)');
console.log(err);
}else{
console.log('mapping created!');
console.log(mapping);
}
});
I had the same error. If you look in the Documentation it states that you have to explicit remove the document after deleting it.
This is the way i am doing a deletion now.
const deleteOne = Model => async (id)=> {
const document = await Model.findByIdAndDelete(id);
if (!document) {
return new Result()
.setSuccess(false)
.setError('Unable to delete Entity with ID: ' + id + '.')
}
//this ensures the deletion from the elasticsearch index
document.remove();
return new Result()
.setSuccess(true)
.setData(document)
}
I dont know what version of mongoosastic you're using but i use mongoosastic#3.6.0 and my indexed doc get deleted whenever i remove it either using Model.findByIdAndRemove or Model.remove. Therefore try to cross check the way you delete you're docs.
I solved the problem by changing the way I delete the data.
I was using:
Quantum.findByIdAndRemove(quantumid)
I switched it to:
Quantum.findById(quantumid, function(err, quantum) {
quantum.remove(function(err, quantum) {
if (err) {
console.log(err);
return;
}
});
});
I did not research the reason for this working, but it solved the problem and I moved on.
I'm using the Mongoose Library for accessing MongoDB with node.js
Is there a way to remove a key from a document? i.e. not just set the value to null, but remove it?
User.findOne({}, function(err, user){
//correctly sets the key to null... but it's still present in the document
user.key_to_delete = null;
// doesn't seem to have any effect
delete user.key_to_delete;
user.save();
});
In early versions, you would have needed to drop down the node-mongodb-native driver. Each model has a collection object that contains all the methods that node-mongodb-native offers. So you can do the action in question by this:
User.collection.update({_id: user._id}, {$unset: {field: 1 }});
Since version 2.0 you can do:
User.update({_id: user._id}, {$unset: {field: 1 }}, callback);
And since version 2.4, if you have an instance of a model already you can do:
doc.field = undefined;
doc.save(callback);
You'll want to do this:
User.findOne({}, function(err, user){
user.key_to_delete = undefined;
user.save();
});
I use mongoose and using any of the above functions did me the requirement. The function compiles error free but the field would still remain.
user.set('key_to_delete', undefined, {strict: false} );
did the trick for me.
At mongo syntax to delete some key you need do following:
{ $unset : { field : 1} }
Seems at Mongoose the same.
Edit
Check this example.
Try:
User.findOne({}, function(err, user){
// user.key_to_delete = null; X
`user.key_to_delete = undefined;`
delete user.key_to_delete;
user.save();
});
if you want to remove a key from collection try this method.
db.getCollection('myDatabaseTestCollectionName').update({"FieldToDelete": {$exists: true}}, {$unset:{"FieldToDelete":1}}, false, true);
Could this be a side problem like using
function (user)
instead of
function(err, user)
for the find's callback ? Just trying to help with this as I already had the case.
Mongoose document is NOT a plain javascript object and that's why you can't use delete operator.(Or unset from 'lodash' library).
Your options are to set doc.path = null || undefined or to use Document.toObject() method to turn mongoose doc to plain object and from there use it as usual.
Read more in mongoose api-ref:
http://mongoosejs.com/docs/api.html#document_Document-toObject
Example would look something like this:
User.findById(id, function(err, user) {
if (err) return next(err);
let userObject = user.toObject();
// userObject is plain object
});
the problem with all of these answers is that they work for one field. for example let's say i want delete all fields from my Document if they were an empty string "".
First you should check if field is empty string put it to $unset :
function unsetEmptyFields(updateData) {
const $unset = {};
Object.keys(updatedData).forEach((key) => {
if (!updatedData[key]) {
$unset[key] = 1;
delete updatedData[key];
}
});
updatedData.$unset = $unset;
if (isEmpty(updatedData.$unset)) { delete updatedData.$unset; }
return updatedData;
}
function updateUserModel(data){
const updatedData = UnsetEmptyFiled(data);
const Id = "";
User.findOneAndUpdate(
{ _id: Id },
updatedData, { new: true },
);
}
I believe that, if you desire remove a specific field into a collection, you should do this:
User.remove ({ key_to_delete: req.params.user.key_to_delete});
you can use
delete user._doc.key