Nodejs, MongoDB - Determine if Document in Collection was Updated or Inserted - javascript

I am calling the mongoDB update function with {upsert:true} to insert a new document if the given _id does not exist. I would like to determine if the document was inserted or update. Much like this question I found using java but only using Nodejs.
how to check if an document is updated or inserted in MongoDB
Here is my DB call.
app.post('/mongoSubmit', function(req, res) {
console.log("This is the req.body" + JSON.stringify(req.body, null, 4));
var updateCustomer = function(db, callback){
db.collection('customers1').update(
{_id:req.body.email},
{ first: req.body.firstName,
last: req.body.lastName,
phone: req.body.phone,
email: req.body.email,
subjectIndex: req.body.subject,
messageIndex: req.body.message
},
{ upsert: true},
function(err, result){
if(err){console.log("database error" + err)}
callback(result);
}
);
}
MongoClient.connect(url, function(err, db){
updateCustomer(db, function(result){
console.log("these are the results" + JSON.stringify(result, null, 4));
/*
** Return Either
*
these are the results{
"ok": 1,
"nModified": 0,
"n": 1,
"upserted": [
{
"index": 0,
"_id": "sjr6asdfsadfsadf28#gmail.com"
}
]
}
/*
*
* or
these are the results{
"ok": 1,
"nModified": 1,
"n": 1
}
//BUT *************** Problem using this Value *********************
console.log("this is the value of Modified" + result.nModified);
/*
** Returns undefined
*/
if(result.nModified == 1){
console.log("Updated document");
}
else{
console.log("Inserted document");
}
db.close();
res.render('applications', {
title:"Title"
});
});
});
});
I have also tried for test doing
if(result.hasOwnProperty('upserted'){
//log an Insert
if(result.upserted == true {
//log an Insert
if(result.nModified == 1){
// log an update
if(result.nModified == true){
//log an update
and also adding upserted as a parameter to the callback which I found from a different forum.
function(err, result, upserted){
//callback function
//upserted was undefined
})
My result is confusing. How I could log an object with a property value but when I try to log that specific property it comes up undefined?
Could anyone explain why this might happen in javascript?
or
Suggest another solution for determining if a document in a collection was updated or inserted?
Thank You

The result is a structure that contatins it's own property "result" which has the sub-properties. So you need to inspect at the right level:
var async = require('async'),
mongodb = require('mongodb'),
MongoClient = mongodb.MongoClient;
MongoClient.connect('mongodb://localhost/test',function(err,db) {
db.collection('uptest').update(
{ "a": 1 },
{ "$set": { "b": 2 } },
{ "upsert": true },
function(err,result) {
if (err) throw err;
if (result.result.hasOwnProperty('upserted') ) {
console.log( JSON.stringify( result.result.upserted, undefined, 2 ) );
}
console.log( "matched: %d, modified: %d",
result.result.n,
result.result.nModified
);
}
);
});
On a first run you will get the "array" of "upserted" like this:
[
{
"index": 0,
"_id": "55a4c3cfbe78f212535e2f6a"
}
]
matched: 1, modified: 0
On a second run with the same values then nothing is added or modified:
matched: 1, modified: 0
Change the value of "b" and "modified" is counted since the data actually changed.

Related

Mongodb find query does not work when the condition variable value is passed through loop in node js

for (var j = 0; j < u1.similar_users.length; j++) {
var pp = u1.similar_users[j];
console.log(pp);
db.collection('userdata').find({ user: pp }, { restaurants: true, _id: false }), (function(err, res) {
console.log(res);
for (var tt = 0; tt < res.length; tt++) {
console.log(res[tt]);
var u1 = res[tt];
//console.log(u1.similar_users.length);
console.log(u1.restaurants);
}
});
}
Userdata collection is as follows:
{
"user": "falak",
"restaurants": [
{
"name": "subway",
"address": "1, Kondeshwar Bhuvan, Tilak Road, Ghatkopar East, Mumbai",
"locality": "Ghatkopar East",
"city": "Mumbai",
"cuisines": "North Indian, South Indian, Chinese"
}],
"similar_users": [
" ashu"
]
}
Here,i trying to find and display the resturant of the users ,and the value of the user is passed dynamically .But it is unable to access the 'pp' variable inside the find query. Whereas it works well and gets displayed in the console.Also if the value for user var is passed manually such as "user: 'abc' "
it works,but it is not working inside loop.As a result ,the res var after the find query also returns 0 as the length,as no data is fetched using find().Please help
In your solution the problem must that you are not calling a callback properly, try this:
for(var j=0;j<u1.similar_users.length;j++)
{
var pp=u1.similar_users[j];
console.log(pp); // Make sure you have the correct values
db.collection('userdata')
.find( {user:pp}, {restaurants:1,_id:0} )
.toArray((error, docs) => { // chaining toArray method!!
if (error) return process.exit(1);
console.log(docs);
// other stuff
});
}
But as #Molda is pointing out, you should delegate in the DB to perform all the searching, something like this:
var ppArray = []; // An array to store all the values you want to search
for(var j=0;j<u1.similar_users.length;j++)
pp.push(u1.similar_users[j]); // Populate the array
console.log(ppArray);
db.collection('userdata')
.find( { user: { $in : ppArray} }, {restaurants:1,_id:0} ) // Search all the documents
.toArray((error, docs) => {
if (error) return process.exit(1);
console.log(docs);
// other stuff
});
I just looked at your code more closely and noticed in this code
...._id: false }), (function(err...
those parentheses ), ( are not supposed to be there.
This code db.collection(..).find() has esentially no connection to the next function (function(...){....})
Your code written to show the mistake you made:
db.collection('userdata').find({ user: pp }, { restaurants: true, _id: false });
// i replaced , with ; since it has same effect here
// this is immediately invoked function expression
// which has nothing to do with the code above
// both err and res are undefined no matter what the above query returns
(function(err, res) {
console.log(res);
for (var tt = 0; tt < res.length; tt++) {
console.log(res[tt]);
var u1 = res[tt];
//console.log(u1.similar_users.length);
console.log(u1.restaurants);
}
});
This should work as expected
db.collection('userdata').find({ user: { $in: u1.similar_users }, { restaurants: true, _id: false }, function(err, res) {
console.log(res);
});

javascript undefined, when I just logged it

So I just posted a Q about a nested date object and got a speedy answer, felt kinda silly, it was obvious, but no sooner did I get one correct response when something else throw an undefined error.
I'm inside a method call that "finds" a key, and then I want to use the data in that key for other things
This :
Coupon.findKey( req.params._key, (err, key) => {
if ( err ) {
return res.status(400).send(err);
}
console.log('---------- key '+key+'----------');
});
Gives me this:
---------- key { _id: 5a72c5cbe617796370219fb3, token: 'mWJhRlytyjaxztWfsP6tpH7PccEpSfkemZqyt9pf26e4fI1b32e5Qun8LfLKmkhXMytFtB7QYHHLUgGV0V7AwUB055Cp78Old2IrBHlmgDDFl6qYxe05cgTFLzjmzuAZ', user_id: 5a72c5cbe617796370219fb2, type: 'registration', __v: 0, date: { redeemed: null, issued: 2018-02-01T07:46:19.449Z } }----------
clearly - Coupon.findKey() returned an object. That object "appears" to have _id and user_id available.
However if I do this
Coupon.findKey( req.params._key, (err, key) => {
if ( err ) {
return res.status(400).send(err);
}
console.log('---------- key '+ key._id +'----------');
});
I get
---------- key undefined----------
WHAT THE HECK. Javascript, you break my will...
Help anyone....
And my frustration mounts
mongoose not returning a record
key seems to be an array.
Get the first entry from that array: key[0]._id
key[0] is:
{
"_id": "5a72c5cbe617796370219fb3",
"key": "mWJhRlytyjaxztWfsP6tpH7PccEpSfkemZqyt9pf26e4fI1b32e5Qun8LfLKmkhXMytFtB7QYHHLUgGV0V7AwUB055Cp78Old2IrBHlmgDDFl6qYxe05cgTFLzjmzuAZ",
"user_id": "5a72c5cbe617796370219fb2",
"type": "registration",
"__v": 0,
"date": {
"redeemed": null,
"issued": "2018-02-01T07:46:19.449Z"
}
}

MongoDB MonkAPI setting a variable based on find result that is available outside the db request

I'm trying to set a variable based on the result of a find through Monk API on MongoDB in a Node JS application (it's my first time of using MongoDB).
This is an example of the code I have;
var variableIWantToSet;
var collection = req.db.get('myCollection');
collection.find( { foo: 'bar' },{
fields : { myTargetField: 1, _id: 0},
limit : 1,
sort : {$natural : -1}
}
, function(err, doc) {
if (err) {
console.log(err);
}
variableIWantToSet = doc[0].myTargetField;
});
console.log(variableIWantToSet);
If I console.log(doc[0].myTargetField) within the function I get the right value, but the console.log(variableIWantToSet) returns undefined.
Help appreciated. Thanks.
the console.log is outside the callback. so that it's undefined. Put it in the callback.
var collection = req.db.get('myCollection');
collection.find( { foo: 'bar' },{
fields : { myTargetField: 1, _id: 0},
limit : 1,
sort : {$natural : -1}
}
, function(err, doc) {
if (err) {
console.log(err);
}
var variableIWantToSet = doc[0].myTargetField;
console.log(variableIWantToSet);
});
for making it easier to understand :
//The callback function will be call after the mongodb response right value.
var callback = function(err, doc) {
if (err) {
console.log(err);
}
variableIWantToSet = doc[0].myTargetField;
console.log(variableIWantToSet); // return doc[0].myTargetField;
};
var variableIWantToSet;
var collection = req.db.get('myCollection');
collection.find( { foo: 'bar' },{
fields : { myTargetField: 1, _id: 0},
limit : 1,
sort : {$natural : -1}
}
, callback);
console.log(variableIWantToSet); // return undefined;
if you don't understand about callback, google it, it's the basic of asynchronous programming, which makes javascript different.

Update field in sub document mongoose

My parent model
var GameChampSchema = new Schema({
name: String,
gameId: { type: String, unique: true },
status: Number,
countPlayers: {type: Number, default: 0},
companies: [
{
name: String,
login: String,
pass: String,
userId: ObjectId
}
],
createdAt: {type: Date, default: Date.now},
updateAt: Date
})
I need insert userId property in first child where he is not set
So, need this action only on parent with condition ({status: 0, countPlayers: { $lt: 10 })
Since this is an embedded document it is quite easy:
If you want to update a document that is the first element of the array, that doesn't have a userId
db.collection.update(
{
"status": 0,
"countPlayers": {"$lt": 10 },
"companies.userId": {"$exists": false }
},
{ "$set": {"companies.$.userId": userId } }
)
Which would be nice, but apparently this doesn't match how MongoDB processes the logic and it considers that nothing matches if there is something in the array that does have the field present. You could get that element using the aggregation framework but that doesn't help in finding the position, which we need.
A simplified proposal is where there are no elements in the array at all:
db.collection.update(
{
"status": 0,
"countPlayers": {"$lt": 10 },
"companies.0": {"$exists": false }
},
{ "$push": {"userId": userId } }
)
And that just puts a new thing on the array.
The logical thing to me is that you actually know something about this entry and you just want to set the userId field. So I would match on the login:
db.collection.update(
{
"status": 0,
"countPlayers": {"$lt": 10 },
"companies.login": login,
},
{ "$set": {"companies.$.userId": userId } }
)
As a final thing if this is just updating the first element in the array then we don't need to match the position, as we already know where it is:
db.collection.update(
{
status: 0,
countPlayers: {"$lt": 10 }
},
{ $set: { "companies.0.userId": userId } }
)
Tracing back to my logical case, see the document structure:
{
"_id" : ObjectId("530de54e1f41d9f0a260d4cd"),
"status" : 0,
"countPlayers" : 5,
"companies" : [
{ "login" : "neil" },
{ "login" : "fred", "userId" : ObjectId("530de6221f41d9f0a260d4ce") },
{ "login": "bill" },
]
}
So if what you are looking for is finding "the first document where there is no userId", then this doesn't make sense as there are several items and you already have a specific userId to update. That means you must mean one of them. How do we tell which one? It seems by the use case that you are trying to match the information that is there to an userId based on information you have.
Logic says, look for the key value that you know, and update the position that matches.
Just substituting the db.collection part for your model object for use with Mongoose.
See the documentation on $exists, as well as $set and $push for the relevant details.
Big thanks.
I solved his problem
exports.joinGame = function(req, res) {
winston.info('start method');
winston.info('header content type: %s', req.headers['content-type']);
//достаем текущего пользователя
var currentUser = service.getCurrentUser(req);
winston.info('current username %s', currentUser.username);
//формируем запрос для поиска игры
var gameQuery = {"status": 0, "close": false};
gameChamp.findOne(gameQuery, {}, {sort: {"createdAt": 1 }}, function(error, game) {
if (error) {
winston.error('error %s', error);
res.send(error);
}
//если игра нашлась
if (game) {
winston.info('Append current user to game: %s', game.name);
//добавляем userId только к одной компании
var updateFlag = false;
for (var i=0; i<game.companies.length; i++) {
if (!game.companies[i].userId && !updateFlag) {
game.companies[i].userId = currentUser._id;
updateFlag = true;
winston.info('Credentials for current user %s', game.companies[i]);
//если пользовател последний закрываем игру и отправляем в bw, что игра укомплектована
if (i == (game.companies.length-1)) {
game.close = true;
winston.info('game %s closed', game.name);
}
}
}
//сохраняем игру в MongoDB
game.save(function(error, game) {
if (error) {
winston.error('error %s', error);
res.send(error);
}
if (game) {
res.send({ game: game })
winston.info('Append successful to game %s', game.name);
}
});
}
});
}

MongoDB : adding element to inner json object while both key-value stored in variables

i am trying to update a document in mongo db with nodejs native driver.
initially it was inserted like:
matches {
_id:2001,
requester:"MITH",
accepter:"NIKK",
toss:"MITH",
bat:"NIKK",
scores:{"MITH":220},
status:0,
won:"MITH"
}
now i need to update the document where i need to insert a new element "NIKK":198 to scores object to make it scores:{"MITH":220,"NIKK":198}
problem is the key comes in a variable only. and when i update it is not updating
Below is the code with which i am trying
var _jsonMatch = {status:4};
var _scorepush = {}
_scorepush[variablevalue] = 198; // variablevalue in reference above is NIKK
var data = {"$set": _jsonMatch,"$push": {"scores":_scorepush} }
mith.findAndModify({_id:mith.db.bson_serializer.ObjectID.createFromHexString(matchId)},
[],
data,
{ upsert: true,new:true },
function(error, match){
if( error ) callback(error);
else callback(null, match);
});
EDIT :
I tried $addToSet instead of $push and i got the below error in callback with data undefined.
{ [MongoError: Cannot apply $addToSet modifier to non-array] name:
'MongoError', lastErrorObject: { err: 'Cannot apply $addToSet
modifier to non-array',
code: 12591,
n: 0,
connectionId: 56,
ok: 1 }, errmsg: 'Cannot apply $addToSet modifier to non-array', ok: 0 } undefined
You need to build up your $set object programmatically to use dot notation in the key that sets 'scores.NIKK'. So to update the doc you've shown above:
variablevalue = 'NIKK';
var set = {
status: 4
};
set['scores.' + variablevalue] = 198;
mith.findAndModify({_id: 2001},
[],
{ $set: set },
{ upsert: true, new: true },
function(error, match){
if( error ) callback(error);
else callback(null, match);
}
);
Note: the awkwardness of this is because you're using dynamic keys that you need to build up at run-time. Consider re-working your schema so that scores is an array that looks something like this instead:
scores: [{name: 'MITH', value: 220}, {name: 'NIKK', value: 198}]
I think you want $set instead of $push:
var _jsonMatch = {status:4};
var _scorepush = {}
_scorepush[variablevalue] = 198; // variablevalue in reference above is NIKK
_jsonMatch["scores"] = _scorepush;
var data = {"$set": _jsonMatch };
mith.findAndModify({_id:mith.db.bson_serializer.ObjectID.createFromHexString(matchId)},
[],
data,
{ upsert: true,new:true },
function(error, article){
if( error ) callback(error);
else callback(null, article);
});

Categories