Update many records by id - node.js

i'm woking with mongoose on a project and i have the following issue:
I need to update many records by its ids ( these ids was stored in an array ), i've tried this method:
Collection.update({$in:{"_id":ids}}, {$set:{data_of_id}}, {upsert : true},
{"multi": true}, function(err, res){
if(err){ console.log(err) };
console.log(res);
});
ids[] is the ids of the collection i need to update, and data_of_id is the new records wich will replace the old records. But i don't know how to associate these ids with each record in the array. I tried to put the update query into a foreach method too, but no success. The query above don't return any error or message, the called method was executed but don't execute the query.

The $in syntax is incorrect, it should be:
{ field: { $in: [<value1>, <value2>, ... <valueN> ] } }
So, you should write it like this:
Collection.update({_id: {$in: ids}}, ...);

I've solved doing by this way:
datas.forEach(function(data){
Collection.update({"_id":data._id},
data, {upsert : true},{new : true}, function(err, res){
if(err) console.log(err);
});
});

Related

MongoDB $pull Query Doesn't Work Properly

Guys I want to make a unfollow request with $pull qıery but it doesnt work. How to solve this?
Also this method works fine with $push query when I want to follow request user but it doesnt work with $pull.
My app.js:
app.post('/unfollow/:id', function(req, res){
User.find(req.user
).exec(function(err, user){
if(err){
console.log(err);
}
User.find({"username":req.params.id}, function(err, friend){
if(err){
console.log(err);
}
User.update(user,{$pull: { follow: friend}}, function(err){
if(err){
console.log(err);
}else{
res.send("Success")
}
});
});
});
});
This is my how user's follow look like:
{ follow:
[ 5edfe8f3bfc9d677005d55ca,
5edfe92fbfc9d677005d55cc,
5ee2326cc7351c5bb0b75f1a ],
I will take friend id from this array.
And my user model(Follow part):
follow:[{
type: ObjectId,
}]
If pull doesnt work can you suggest me queries or ways to do unfollow request.
User.find({ username: req.params.id } would return a document but looks like you do store ObjectIds in follow field. I except changing $pull: { follow: friend } to $pull: { follow: friend._id } should solve the problem.

Update data in MongoDB with Mongojs using findAndModify()

Yet another first-timer problem here. This gets data from a database and displays it in some text fields (that part is not shown in the code below) and after the user edits it the data should be updated in the database via the findAndModify() method and I think this is where the issue lies. There are no errors, it just doesn't do anything. EDIT The following error is received: MongoError: Either an update or remove=true must be specified
server.js
MongoClient.connect("mongodb://user:secretPassword#aws-us-east-1-portal.7.dblayer.com:10712,aws-us-east-1-portal.10.dblayer.com:10316/database", function(err, db) {
if (err) throw err;
var contactList = db.collection("contactList");
app.put('/contactList/:id', function(req, res) {
var id = req.params.id;
console.log("edited: " + req.body.name); //works up until here
contactList.findAndModify({
query: {_id: mongojs.ObjectId(id)},
update: {$set: {name: req.body.name, email: req.body.email, number: req.body.number}},
new: true
}, function (err, doc) {
res.json(doc);
})
});
controller.js
$scope.update = function() {
$http.put('/contactList/' + $scope.contact._id, $scope.contact).success(function(response) {
refresh();
})
};
If this were me I would first do a couple of things:
Before your call to findAndModify just do a simple find using your query. Make sure you can actually find the object using your query. If that works you know that the 'find' part of the findAndModify is probably ok.
Do some console logging inside the callback handler of the findAndModify call. As it stands you do not do anything if an err is returned from the findAndModify call. It is possible your call is returning an error that you are just ignoring and it may provide some additional insight into your problem.
I would try these two first and see if it helps.
Update:
Example using native:
collection.findAndModify(
{ field: 'some value' },
[],
{ $set: { field2: 'some new value' } },
{ new:true },
function(err, doc) {
//handle err and doc
});

Mongoose OR operator with _id

I'm using mongoose.
When I do this, it works fine:
userModel.find({ $or:[
{first_name:"Bob"},
{last_name: "Marley"}
]
}, function(err, result){
if(err) //do something;
console.log(result);
});
But when I use _id as one of the expressions, it only looks for the _id and doesn't care about the other expressions:
userModel.find({ $or:[
{_id: "56b426aa1d6c7a642ab1a52d"},
{last_name: "Marley"}
]
}, function(err, result){
if(err) //do something;
console.log(result);
});
Recap:
The first example would either find first name Bob or last name Marley.
But the second example would only find either that exact id that I provided or null.
What am I doing wrong?
The MongoDB _id field is a special type of field and needs to be initialised as follows, before it can be used in the query:
new Mongoose.Types.ObjectId("56b426aa1d6c7a642ab1a52d")
or
var ObjectId = require('mongoose').Types.ObjectId;
new ObjectId("56b426aa1d6c7a642ab1a52d");

How to check if Mongo's $addToSet was a duplicate or not

I am using Mongoskin + NodeJS to add new keywords to MongoDB. I want to notify the user that the entry was a duplicate but not sure how to do this.
/*
* POST to addkeyword.
*/
router.post('/addkeyword', function(req, res) {
var db = req.db;
db.collection('users').update({email:"useremail#gmail.com"}, {'$addToSet': req.body }, function(err, result) {
if (err) throw err;
if (!err) console.log('addToSet Keyword.' );
});
});
The result does not seem to be of any use since it doesn't state if the keyword was added or not.
At least in the shell you can differentiate if the document was modified or not (see nModified).
> db.test4.update({_id:2}, {$addToSet: {tags: "xyz" }})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test4.update({_id:2}, {$addToSet: {tags: "xyz" }})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
Update for Node
When you use collection.update(criteria, update[[, options], callback]); you can retrieve the count of records that were modified.
From the node docs
callback is the callback to be run after the records are updated. Has
two parameters, the first is an error object (if error occured), the
second is the count of records that were modified.
Another Update
It seems at least in version 1.4.3 the native Mongo Node driver is not behaving as documented. It is possible to work around using the bulk API (introduced in Mongo 2.6):
var col = db.collection('test');
// Initialize the Ordered Batch
var batch = col.initializeOrderedBulkOp();
batch.find({a: 2}).upsert().updateOne({"$addToSet": {"tags": "newTag"}});
// Execute the operations
batch.execute(function(err, result) {
if (err) throw err;
console.log("nUpserted: ", result.nUpserted);
console.log("nInserted: ", result.nInserted);
console.log("nModified: ", result.nModified); // <- will tell if a value was added or not
db.close();
});
You could use db.users.findAndModify({email:"useremail#gmail.com"},[],{'$addToSet': { bodies: req.body }},{'new':false}). Pay attention to new:false switcher, it allows you to get document before update and you could check whether array contained item before update. However, it could be problematic approach if your documents are big, because you analyze it on client side.
P.S. Your original query with $addToSet is wrong: field name is missing.
Edit: I tried to use count returned by update, but it returns 1 for me in all cases. Here is the code I used for test with MongoDB 2.6:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/mtest', function(err, db) {
if(err) throw err;
db.collection('test').insert({_id:1,bodies:["test"]},function(err,item){
db.collection('test').update({_id:1},{$addToSet:{bodies:"test"}}, function(err,affected){
if(err) throw err;
console.log(affected); //1 in console
});
});
});
i am update a array from Collection with this JSON:
{
"<arrayname>":"<value>"
}
route.js
routes.post("/api/:id", Controller.addOne);
Controller.js
async addOne(req, res) {
//juryman id to list add
if (Object.keys(req.body).length === 1) {
console.log("Size 1");
}
await Session.findOneAndUpdate(
{ _id: req.params.id },
{ $addToSet: req.body }
)
.then(function(success) {
res.send("Successfully saved.");
})
.catch(function(error) {
res.status(404).send(error);
});
},
I have five arrays in my Collection and this changes the JSON array name-value and updates correctly, the respectively Collection array. This works only for one item.

Is it possible to return only a certain fields when inserting a new document?

I nedd to get the new document back with _id field only. Something like this:
db.users.insert({name: 'Jonh', age: 27}, {_id: true} , function (err, user) {
if (err) {}
// need to be user with only _id field.
});
How can I do this?
UPDATED
The second parameter to the insert callback is always an array of the inserted objects, and you can't prevent the other fields from being included. However, you can use Array#map to create the result you're looking for:
db.users.insert({name: 'Jonh', age: 27}, {_id: true} , function (err, users) {
if (err) {}
users = users.map(function(user) {
return {_id: user._id};
});
// users now contains objects with just the _id field
});

Resources