mongoose not updating doc inside async.eachSeries - node.js

I am trying to update a doc inside async.eachSeries. But it does not update and I am not getting any error. See the code below.
I want to update the oldest doc, namely field LastDatePresent in that doc with the newest date present in both docs. So I have two duplicate docs based on UrlLink, and I want to update the oldest doc based on _id with the newest date in both docs. Example docs:
{
"_id": "older id",
"Date": ISODate("2017-08-25T00:00:00.000Z"),
"UrlLink": "www.myurl.com"
"LastDatePresent": ISODate("2017-08-30T00:00:00.000Z") //Should be updated to "LastDatePresent": ISODate("2017-08-31T00:00:00.000Z")
}
{
"_id": "newer id",
"Date": ISODate("2017-08-25T00:00:00.000Z"),
"UrlLink": "www.myurl.com"
"LastDatePresent": ISODate("2017-08-31T00:00:00.000Z")
}
Thankful for any suggestions:
async.eachSeries(aggres, function(member, callback2) {
myTable.find({
"UrlLink": member.UrlLink,
"Date": member.Date,
}, {
_id: 1,
UrlLink: 1,
Date: 1,
LastDatePresent: 1
}, {
sort: {
'_id': 1
}
}, function(err, post) {
var latestdate = post[0].LastDatePresent > post[1].LastDatePresent ? post[0].LastDatePresent : post[1].LastDatePresent;
myTable.update({
"UrlLink": post[0].UrlLink,
"Date": post[0].Date
}, {
$set: {
LastDatePresent: latestdate //NOT UPDATING HERE!
}
},
function(err, result) {
console.log("saving DATA");
callback2();
});
});
}, function(err) {
console.log("DONE");
});

Related

Mongoose - replace all array elements

I want to replace all array's elements in 'prices' filed as below:
{
"name": "My customer name"
"taxCode":123456
"prices":
[
{
"name": "Chocolate",
"unitPrice": 10
},
{
"name": "Cookie",
"unitPrice": 9
}
]
}
The JSON that uses to change 'prices' is:
{
"prices":
[
{
"name": "Chocolate1",
"unitPrice": 10
},
{
"name": "Candy",
"unitPrice": 5
}
]
}
And here is my code to replace the 'prices' array
router.route('/:obj/:id')
.put((req, res) => {
const PObj = require('../models/customer');
PObj.findById(req.params.id, (err, doc) => {
if (err) {
console.log('Lookup error: ' + err);
res.status(500).send('Error');
} else if (doc) {
doc.update({$set: req.body}, (err, task) => {
res.status(200).json(task);
}); } else {
res.status(404).send('Something is wrong');
}
});
});
After code executed is done but without any changes in Mongo DB. Please help me to correct my code. Thank!
If your req.body prints that prices array then it has to be req.body.prices, also rather than fetching the document & updating it - Which is a two- way process, You can try this :
router.route("/:obj/:id").put((req, res) => {
const PObj = require("../models/customer");
PObj.findByIdAndUpdate(
req.params.id, /** this 'req.params.id' has to be `_id` value of doc in string format */
/** internally mongoose will send this as { $set: { prices: req.body.prices }} which will replace `prices` array will new array,
* Just in case if you wanted to push new values, have to manually do { $push: { prices: req.body.prices }} each object */
{ prices: req.body.prices },
{ new: true }, /** returns updated doc, this option is not needed if you don't need doc - by default it returns old doc */
(err, doc) => {
if (err) {
console.log("Lookup error: " + err);
res.status(500).send("Error");
} else if (doc) {
res.status(200).json(task);
} else { /** `doc` value will be null if no doc is not found for given id */
res.status(404).send("Something is wrong");
}
}
);
});
Ref : .findByIdAndUpdate()

need to update field with condition in mongodb

I am doing currently doing as
if (part.qty) {
part.status = 'In Stock';
}
const part = new partsModel(part);
return part.save();
is it possible do this in MongoDB query only without using if statement both insert and update
You can try something like:
const filterObj = {
"$or": [{
"qty": {
"$exists": true
}
}, {
"qty": {
"$ne": null
}
}, {
"qty": {
"$ne": 0 //based on what type of value you have in qty
}
}]
};
const updateObj = {
"$set": {
"status": "In Stock"
}
};
partsModel.update(filterObj, updateObj)
.then(result => {
console.log(result);
})
.catch(err => {
console.log(err);
});
This will update the first matching record with our filters. If you wanna update all matching records use updateMany() instead.
Check out the official mongoose docs for more details.
P.s: You may need some modifications as i couldn't get a chance to try the code. hope this helps :)

create a new object Id in mongoDB using node js

I am using the below code to insert data to mongodb
router.post('/NewStory', function (req, res) {
var currentObject = { user: userId , story : story , _id:new ObjectID().toHexString() };
req.db.get('clnTemple').findAndModify({
query: { _id: req.body.postId },
update: { $addToSet: { Stories: currentObject } },
upsert: true
});
});
This code is working fine if i remove the _id:new ObjectID().toHexString()
What i want to achieve here is that for every new story i want a unique _id object to be attached to it
What am i doing wrong?
{
"_id": {
"$oid": "55ae24016fb73f6ac7c2d640"
},
"Name": "some name",
...... some other details
"Stories": [
{
"userId": "105304831528398207103",
"story": "some story"
},
{
"userId": "105304831528398207103",
"story": "some story"
}
]
}
This is the document model, the _id that i am trying to create is for the stories
You should not be calling .toHexString() on this as you would be getting a "string" and not an ObjectID. A string takes more space than the bytes of an ObjectId.
var async = require('async'),
mongo = require('mongodb'),
db = require('monk')('localhost/test'),
ObjectID = mongo.ObjectID;
var coll = db.get('junk');
var obj = { "_id": new ObjectID(), "name": "Bill" };
coll.findAndModify(
{ "_id": new ObjectID() },
{ "$addToSet": { "stories": obj } },
{
"upsert": true,
"new": true
},
function(err,doc) {
if (err) throw err;
console.log(doc);
}
)
So that works perfectly for me. Noting the "new" option there as well so the modified document is returned, rather than the original form of the document which is the default.
{ _id: 55c04b5b52d0ec940694f819,
stories: [ { _id: 55c04b5b52d0ec940694f818, name: 'Bill' } ] }
There is however a catch here, and that is that if you are using $addToSet and generating a new ObjectId for every item, then that new ObjectId makes everything "unique". So you would keep adding things into the "set". This may as well be $push if that is what you want to do.
So if userId and story in combination already make this "unique", then do this way instead:
coll.findAndModify(
{
"_id": docId,
"stories": {
"$not": { "$elemMatch": { "userId": userId, "story": story } }
}
},
{ "$push": {
"stories": {
"userId": userId, "story": story, "_id": new ObjectID()
}
}},
{
"new": true
},
function(err,doc) {
if (err) throw err;
console.log(doc);
}
)
So test for the presence of the unique elements in the array, and where they do not exist then append them to the array. Also noting there that you cannot do an "inequality match" on the array element while mixing with "upserts". Your test to "upsert" the document should be on the primary "_id" value only. Managing array entries and document "upserts" need to be in separate update operations. Do not try an mix the two, otherwise you will end up creating new documents when you did not intend to.
By the way, you can generate an ObjectID just using monk.
var db = monk(credentials.database);
var ObjectID = db.helper.id.ObjectID
console.log(ObjectID()) // generates an ObjectID

Issue with a simple mongo/monk findAndModify query

Just a note I am fairly new to mongo and more notably very new to using node/js.
I'm trying to write a query to insert new documents or update already existing documents in my collection.
The proposed structure of the collection is:
{ _id: xxxxxxx, ip: "xxx.xxx.xxx.xxx:xxxxxx", date: "xx-xx-xx xxxx" }
Note that my intention is a store an fixed length int for the _id rather than the internal ObjectId (is this possible/considered bad practice?). The int is guaranteed to be unique and comes from another source.
var monk = require('monk');
var db = monk('localhost:27017/cgo_schedule');
var insertDocuments = function(db, match) {
var db = db;
var collection = db.get('cgo_schedule');
collection.findAndModify(
{
"query": { "_id": match.matchId },
"update": { "$set": {
"ip": match.ip,
"date": match.date
},
"$setOnInsert": {
"_id": match.matchId,
}},
"options": { "new": true, "upsert": true }
},
function(err,doc) {
if (err) throw err;
console.log( doc );
}
);
}
This doesn't work at all however. It doesn't insert anything to the database, but it also gives no errors, so I have no idea what I'm doing wrong.
The output (for console.log (doc)) is null.
What am I doing wrong?
The Monk docs aren't much help, but according to the source code, the options object must be provided as a separate parameter.
So your call should look like this instead:
collection.findAndModify(
{
"query": { "_id": match.matchId },
"update": {
"$set": {
"ip": match.ip,
"date": match.date
}
}
},
{ "new": true, "upsert": true },
function(err,doc) {
if (err) throw err;
console.log( doc );
}
);
Note that I removed the $setOnInsert part as the _id is always included on insert with an upsert.

How to query and update document by using single query?

I have documents likes the following:
{
"_id": "538584aad48c6cdc3f07a2b3",
"startTime": "2014-06-12T21:30:00.000Z",
"endTime": "2014-06-12T22:00:00.000Z",
},
{
"_id": "538584b1d48c6cdc3f07a2b4",
"startTime": "2014-06-12T22:30:00.000Z",
"endTime": "2014-06-12T23:00:00.000Z",
}
As you can see the documents above have startTime and endTime. I need to update some document that don't overlap others. I can make things to work by using two queries:
var event_id = "538584b1d48c6cdc3f07a2b4";
var event = {
startTime: "2014-06-12T21:30:00.000Z"
endTime: "2014-06-12T23:30:00.000Z"
};
Model.count({
_id: {$ne: event_id },
"$or": [
{"$and": [
{"startTime":{"$lte":event.startTime},"endTime":{"$gt":event.startTime}},
{"startTime":{"$lte":event.endTime},"endTime":{"$lt":event.endTime}}
]},
{"$and":[
{"startTime":{"$lte":event.startTime},"endTime":{"$gte":event.startTime}},
{"startTime":{"$lte":event.endTime},"endTime":{"$gte":event.endTime}}
]}
]
}, function (err, count) {
if (err) return next(err);
if (count) {
return next(new Error('Event overlapping'));
}
return Model.findOneAndUpdate({_id: event_id}, event, function (err, event) {
if (err) return next(err);
return res.json(200, event);
});
});
As you can see from the code above I do first query for checking of existing event that could overlaps. And then I do update.
Is it possible to make updating by using single query?

Resources