$push in nested field works wonky in mongoose? - node.js

I have a schema that's something like this
firstfield :{
secondfield:{
thirdfield : [ObjectId]
}
}
and i do something like this
models.mymodel.update({_id:ObjectId(logId)}, {$push: {"firstfield.secondfield.thirdfield" : ObjectId(userId)}}, function(err, result) {
console.dir(result);
})
Here's the problem. When i give it an existing logId to search for... after it's done, it deletes the whole row.. and creates another one, somehow managing to increment SOME fields (let's assume i have name field set as : mylog_6 (the current row i want to modify) and the maximum is 105.. it will delete that row and create one and it will set the name as mylog_106.
What gives? :)

Related

insert or update(upsert) in loopback application

I developed an API using Loopback framework, in that i have to insert or update to a table.
My table looks like below:
userid bbid saved id(PK)
1 5 1000 1
So when next time if(bbid = 5) it should update the above row, if bbid =5 is not there it should insert into the above table.
I tried the following:
app.models.modelname.upsert({
bbid: bb.id,
saved: Saved,
userid: 1
}, function(err, res) {});
EDIT for COMPOSITE ID:
app.models.modelname.upsert({
bbid: vvvv.bbid,
userid: 1,
saved: amountSaved
}, function(err, res) {});
Also gone through Loopback doc it says
upsert - checks if the instance (record) exists, based on the designated
ID property, which must have a unique value; if the instance already exists,
the method updates that instance. Otherwise, it inserts a new instance.
But in my case it should check for bbid not id
But its inserting everytime. Please share your ideas. Thanks in advance
EDIT FOR UPSERT:
My process is as follows:
Fetch from table1 and loop that response and calculate the saved and upsert it into another table(table2 (this is where upsert should happen)). Also the fetching from table1 will happen frequently so suppose consider if is happens 2nd time it should update the already present bbid..
You can use the findOrCreate method as follows:
app.models.modelname({where: {bbid:bb.id} }, {bbid:bb.id, saved: Saved, userid:1}, function(err, instance) {
if (err){
cb(null, err);
}
cb(null, instance);
});
There are two methods in loopback one is simple upsert and second is upsertWithWhere.To insert or update based on where condition you must use upsertWithWhere method upsert only inserts the data.
you are using
app.models.modelname.upsert({bbid:bb.id, saved: Saved, userid:1}
,function(err, res){});
instead use
app.models.modelname.upsertWithWhere({bbid:bb.id, saved: Saved, userid:1}
,function(err, res){});
this will solve your problem.
note: this only updates single instance.If multiple instances are returned in where condition result it will throw an error.

Remove a single object from an array of objects in a single document of a collection

I have a problem with which I am struggling for quite some time.Suppose my document is like this
{"owner":"princu7", "books":[{"name":"the alchemist"}, {"name":"the alchemist"}, {"name":"the alchemist"}].
Now what do I do if I have to just remove one single element from the books array based on the matching of the name?I did it like this
var bookName="the alchemist";
var obj={"name":bookName}
db.collection("colName").update({"owner":"princu7"}, {$pull:{books:obj}}, {multi:false})
But the problems is that it removes all the entries in the array which have the name matching to "the alchemist". What I wanted was this
{"owner":"princu7", "books":[{"name":"the alchemist"}, {"name":"the alchemist"}
But what I got was this
{"owner":"princu7", "books":[]}
Upon reading the documentation, it says that pull removes all the instances that match the required condition so maybe that's why it's removing all other entries of the array which match the condition.So what should I do here.Thanks for reading.Really appreciate your help.
See this issue:
https://jira.mongodb.org/browse/SERVER-1014
You cannot achieve what you are trying to do in a single update. A way would be to modify that record in your application & save the changes.
You could use collection.updateOne() with upsert set to true to re-write the record in place. The idea is you get the original document, modify it in your app logic, then re-apply it to the database after removing the element from the array.
function upsert(collection, query, json) {
var col = db.collection(collection);
col.updateOne(query
, { $set : json }
, { upsert : true }
, function (err, result) {
if(err) {
log('error = ', err);
} else {
// no error, call the next function
}
}
);
};
By design, mongodb's $pull operator removes from an existing array all instances of a value or values that match the specified condition.Therefore it will remove all matching {"name":"the alchemist"} elements from the array.
I guess I would use $pop, which only removes the first matching element.
db.collection("colName")
.update({"owner": "princu7"}
, {$pop: {"books": {$match: {"name": "the alchemist"}}}}
, {multi:false}
)

Inserting the records in the table if not exists after sequelize.sync({force:true}) is called

I need to add some records to the table if there is no record exists. For now, I have written the logic to add the records in the callback function of the sequelize.sync({force:true}). I have checked whether the table contains atleast one record, and if not, I have inserted the set of records. Is there any other elegent way to obtain this functionality?
I'm reaaaaaly late to this question, but you can use findOrCreate
Like.findOrCreate({
where: {//object containing fields to found
InstagramPostId: inputLike.InstagramPostId,
InstagramUserId: inputLike.InstagramUserId
},
defaults: {//object containing fields and values to apply
postInstagramPostId: inputLike.postInstagramPostId,
userInstagramUserId: inputLike.userInstagramUserId
}
}).error(function(err){//error handling
console.log(err);
}).then(function(){//run your calllback here
console.log("callback!!");
});
Updated 02/07/2021: Use this code: Tested! Run ok.
Like.findOrCreate({
where: {//object containing fields to found
InstagramPostId: inputLike.InstagramPostId,
InstagramUserId: inputLike.InstagramUserId
},
defaults: {//object containing fields and values to apply
postInstagramPostId: inputLike.postInstagramPostId,
userInstagramUserId: inputLike.userInstagramUserId
}
}).then(function(){//run your calllback here
console.log("callback!!");
}).catch(err => {
res.status(500).send("Error -> " + err);
});

Node.js and MongoDB if document exact match exists, ignore insert

I am maintaining a collection of unique values that has a companion collection that has instances of those values. The reason I have it that way is the companion collection has >10 million records where the unique values collection only add up to 100K and I use those values all over the place and do partial match lookups.
When I upload a csv file it is usually 10k to 500k records at a time that I insert into the companion collection. What is the best way to insert only values that dont already exist into the unique values collection?
Example:
//Insert large quantities of objects into mongo
var bulkInsert = [
{
name: "Some Name",
other: "zxy",
properties: "abc"
},
{
name: "Some Name",
other: "zxy",
properties: "abc"
},
{
name: "Other Name",
other: "zxy",
properties: "abc"
}]
//Need to insert only values that do not already exist in mongo unique values collection
var uniqueValues = [
{
name:"Some Name"
},
{
name:"Other Name"
}
]
EDIT
I tried creating a unique index on the field, but once it finds a duplicate in the Array of documents that I am inserting, it stops the whole process and doesnt proceed to check any values after the break.
Figured it out. If your doing it from the shell, you need to use Bulk() and create insert jobs like this:
var bulk = db.collection.initializeUnorderedBulkOp();
bulk.insert( { name: "1234567890a"} );
bulk.insert( { name: "1234567890b"} );
bulk.insert( { name: "1234567890"} );
bulk.execute();
and in node, the continueOnError flag works on a straight collection.insert()
collection.insert( [{name:"1234567890a"},{name:"1234567890c"}],{continueOnError:true}, function(err, doc){}
Well, I think the solution here is quite simple if I understand correctly your issue.
Since the process is stopped when it finds a duplicated field you should basically check if the value doesn't already exists before to try to add it.
So, for each element in uniqueValues, make a find/findOne query, if it doesn't return any result then add the element, otherwise don't.

Issue with updating new row by using the mongodb driver

How can I add a new row with the update operation
I am using following code
statuscollection.update({
id: record.id
}, {
id: record.id,
ip: value
}, {
upsert: true
}, function (err, result) {
console.log(err);
if (!err) {
return context.sendJson([], 404);
}
});
While calling this first one i will add the row
id: record.id
Then id:value then i have to add id:ggh
How can i add every new row by calling this function for each document I need to insert
By the structure of your code you are probably missing a few concepts.
You are using update in a case where you probably do not need to.
You seem to be providing an id field when the primary key for MongoDB would be _id. If that is what you mean.
If you are intending to add a new document on every call then you probably should be using insert. Your use of update with upsert has an intended usage of matching a document with the query criteria, if the document exists update the fields as specified, if not then insert a new document with the fields specified.
Unless that actually is your goal then insert is most certainly what you need. In that case you are likely to rely on the value of _id being populated automatically or by supplying your own unique value yourself. Unless you specifically want another field as an identifier that is not unique then you will likely want to be using the _id field as described before.

Resources