get Data from a collection in MongoDB using NodeJS - node.js

I am trying to get data from Mongo DB by filtering a nested object.
the collection structure is :
{
"id":"8820624457",
"type":"CreateEvent",
"actor":{
"id":27394937,
"login":"Johnson0608",
"display_login":"Johnson0608",
"gravatar_id":"",
"url":"https://api.github.com/users/Johnson0608",
"avatar_url":"https://avatars.githubusercontent.com/u/27394937?"
},
"repo":{
"id":163744671,
"name":"Johnson0608/test",
"url":"https://api.github.com/repos/Johnson0608/test"
},
"payload":{
"ref":"master",
"ref_type":"branch",
"master_branch":"master",
"description":null,
"pusher_type":"user"
},
"public":true,
"created_at":"2019-01-01T15:00:00Z"
}
I am trying to get data by repo id.
my code is :
collection.find({'repo.id':id}).toArray(function(err, docs) {
console.log(id);
assert.equal(err, null);
console.log("Found the following records");
console.log(docs);
res.status(200).json({docs});
callback(docs);
});
but I am getting empty array, would be grateful is someone can point me to the right direction

MongoDB compares types before values. If your id comes from req.params it's probably passed as string while repo.id seems to be a number. Try to convert your value to number:
const id = +req.params.repoId

Related

How to use $inc operator for variables in MongoDB using Node.JS

I am trying to build a "number of visitors" collection in mongoDb using Node.JS backend of my website. The frontend sends the following info to Node.JS backend as JSON.
isUniqueVisitor - 1 if yes, 0 if no
country - standard country code - "JP", "IN", "UK", etc
My database looks like following
{
"today": 2019-06-07,
"uniqueVisitors": {
"count": 230,
"countries": {
"JP": 102,
"IN": 88,
"UK": 30
}
}
}
It works well if I use $inc with fixed values
Eg. $inc: {count: 1} // for string/integers keys
Eg. $inc: {"uniqueVisitors.count": 1} // inside quotes to access key of a JSON
Main issue:
I am not able to access a document name using variable.
Eg. $inc: {`uniqueVisitors.countries[${req.body.country}]`}
This creates an error as backticks can't be used for Mongo.
I tried with
Eg. $inc: {uniqueVisitors["countries"][req.body.country]}
But even this creates error.
I followed the web and found that mongo $set using variables can be realized by passing the required JSON directly to $set. Hence I resorted to code it the following way.
mongoClient.connect(mongoURL, async function (err, db) {
if (err) throw err;
console.log("Database connected");
// Identifying my document with today's date
var myQuery = {
date: getTodayDate()
};
// Defining the JSON to be passed to uniqueVisitors $inc
var uniqueVisitorsInc = {
"uniqueVisitors": {
"count": 0,
"countries": {}
}
};
// Populating the JSON to be passed to uniqueVisitors $inc => essentially asking to increase count by 1 and increase that country's count by 1
uniqueVisitorsInc["uniqueVisitors"]["count"] = 1;
uniqueVisitorsInc["uniqueVisitors"]["countries"][myData.country] = 1;
var newValues = {
$inc: uniqueVisitorsInc
};
await db.collection("visitorStats").update(myQuery, newValues, {upsert: true});
db.close();
});
The above method worked well on editor but threw the following runtime error:
$inc requires numerical values
Basically asking me to pass values to $inc in {var1: 1, var2: 5} pattern.
Please help me bypass this weird situation.
I know I can do a two step process where I read the values first, increment in variable and $set it in Mongo.
But does anyone know how to overcome this situation using $inc?
If this update were hardcoded to update "JP" only, it'd need to look like:
$inc: { "uniqueVisitors.country.JP": 1 }
So you were almost there with the backtick method but change the syntax a bit and keep the : 1 part like so:
$inc: { [`uniqueVisitors.country.${req.body.country}`]: 1 }

most efficient way to add a calculated field mongoose

Hi I have a fairly large dataset 55K records. I am calculating the moving average for those. Which is the most efficient way to store these results again?
Currently I am doing this. Which leads to extreme amount of records being written one by one. Is there a way for me to write the whole list back in one call if I add the calculated value to the records array?
updated the code with the bulk update. It however fails to update the "MA16" record. Even though I know for sure that there is valid data in the "list" array.
It seems to match the documents but won't update. It will yield a MA16 field in the database that is always null.
Logged output.
deletedCount:0
insertedCount:0
insertedIds:Object {}
matchedCount:150
modifiedCount:0
n:0
nInserted:0
nMatched:150
nModified:0
nRemoved:0
nUpserted:0
ok:1
var bulkUpdateArray = _.map(records, (record, index) => {
return {
updateOne :{
"filter":{_id : record._id},
"update":{$set: {"MA16": list[index]}},
"upsert":true
}
}
});
mongoose.connection.db.collection(req.body.day).bulkWrite(bulkUpdateArray).then(result => {
console.log("Insert result", result);
}).catch(err=>{
//catch the error here
})
You can use BulkWrite to achieve what you want.
Try this:
var bulkUpdateArray = _.map(records, (record, index) => {
return {
updateOne :{
"filter":{_id : record._id},
"update":{$set: {"MA16": list[index]}},
"upsert":true
}
}
})
mongoose.connection.db.collection(req.body.day).bulkWrite(bulkUpdateArray).then(result => {
//check the result of bulk update here
}).catch(err=>{
//catch the error here
})
You can use updateOne operator of bulkWrite.
From official MongoDB docs, bulkWrite has following options:
{ updateOne :
{
"filter" : <document>,
"update" : <document>,
"upsert" : <boolean>,
"collation": <document>,
"arrayFilters": [ <filterdocument1>, ... ]
}
}
Please read MongoDB bulkWrite documentation for more info.
I hope this helps you out.

$in function of mongo db is not working in nodejs as except :(

i want to get all the document from mongo db by the number list provided by the user but
the problem i m facing here is this ...
when i pass the value hardcoded the $in function works fine
but when i pass the req.body.userlist then it give me an empty array although the values are same
routes.post(/contect,function(req,res){
var userList = req.body.userList;
var contectList = ["3423432","23432423","32342"];
console.log(userList); //output ["3423432","23432423","32342"]
User.find({
"phoneNumber" : {
"$in":contectList
}
}.then(function(data){
console.log(data);
})
any one help whats wrong here
problem solved Thanks to Anthony Winzlet
the solution was simple all i need to parse the input as Anthony winzlet said
`You are passing string through postman. Try to parse it User.find({
"phoneNumber"
: { "$in": JSON.parse(userList) }}) – Anthony Winzlet`
it should be an array, so try using the spread operator.
$in
{ phonenumber: { $in: [...conectList] } }

NodeJS mongo driver find statement with projection returning full document

I have below funtion to filter only order_id from info collection.
Instead of getting _id and order_id callback is getting all key, values from database.
Node version: 9.4
Mongo version: 3.4
var listCollections=function (columns,db,callback) {
if (columns.length===0) {
return callback('No columns specified')
}
columns.forEach(function (col) {
query[col]=true;
});
db.collection('info').find({},{order_id:true}).toArray(function (mongoError,result) {
console.log(result);
});
};
Please correct me here, but as far as documentation of mongo driver goes, my syntax is correct.
How do I get only specified columns from collection?
find method of the Collection accepts a single parameter in nodejs driver - the query itself.
projection is applied to the cursor:
db.collection('info')
.find({})
.project({order_id:1})
.toArray(function (mongoError,result) {
console.log(result);
});
Use "fields" option.
**db.collection('info').find({},{fields:{_id:0,name:1}}).toArray(function (mongoError,result) {
console.log(result);
})**

Mongoose - Modle.update() updates wrong document - Cast Error

I need some help to clear some things up.
I have a Model:
var Event = new Schema({
event_code: String
, segments: [Segment]
});
The creation of new documents work very well like perfect. When it comes to update certain documents I ran into some troubles.
When I do this (code below): = it only updates the first document, even if the id does not match
function edit_event (id, new_name, callback) {
Event.update(id, {$set:{event_code: new_name}}, function(err, doc) {
if (err) throw err;
callback();
});
}
When I do this (code below): = it gives me an Error (see below)
function edit_event (id, new_name, callback) {
Event.findByIdAndUpdate(id, {$set:{event_code: new_name}}, function(err, doc) {
if (err) throw err;
callback();
});
}
Error when using findByIdAndUpdate: Cast to ObjectId failed for value ""58fdbde31bff83141b376508"" at path "_id" for model "Event"
Please, i'm desperate :! :/
UPDATE
I figured out that the id that i'm trying to pass get stored with "" around it, so when i am looking for document with matching ID it puts an extra pair of "" around it so it ends up like ""id""
UPDATE 2
When I am listing all my documents, it returns:
{ _id: 58fdbde31bff83141b376508,
event_code: 'TestABC',
__v: 0,
segments: [] }
Then when i store the id in an HTML form it adds extra pair of "" around it ... that's not the case with event_code. Why is that ?
Looks like you performed unneeded JSON.stringify and that's why you get quotes around the id. Calling JSON.parse should solve the issue:
Event.findByIdAndUpdate(JSON.parse(id), {$set:{event_code: new_name}}, ...

Resources