Finding max field value in mongodb using node - node.js

I am new in mongodb and node. I am trying to find the max value for a field (userId). But it returns nothing.
My code is
EventSchema.static("createUser",function(event,user,callback){
var That = this;
var max_usr_Id = '';
async.waterfall([
function(callback) {
That.find({"userId" : {"$ne" : ""}, "$and" : [{"userId" : {"$exists" : 1}}]}).sort({"_id" : -1}).limit(1).select("userId").exec(function(err, doc)
{
if(err)
{
console.log('User ID ERROR-');
callback({error:err,message:"Error getting max User ID"});
}else {
console.log('User ID-');
console.log(doc.userId);
max_usr_Id = doc.userId;
console.log(max_usr_Id);
}
});
console.log(max_usr_Id);
},
});
For some reason the control doesn't go inside the find function. When I try the following query in mongodb shell it works.
db.users.find({
"userId" : {
"$ne" : ""
},
"$and" : [
{
"userId" : {
"$exists" : true
}
}
]
}).sort({
"_id" : -1.0
}).limit(1);
Any help is highly appreciated. Thanks in advance.

The $and is not used in the proper way, try with:
That.find({ $and: [
{ "userId": { $ne: "" } },
{ "userId": { $exists: true } }
] }).sort( ...
Take a look at the $and documentation.
Edit
After seen the comments, the problem must be in the way the logging is made. You need to call toArray to get a collection, and then iterate over it (with forEach for instance):
...find( ... ).toArray(function(err, docs) {
// Print each document returned
docs.forEach(function(doc) {
console.log(doc.userId);
});
});

Related

How do i retrieve just the child-object in Azure Cosmos using mongoose and Node.js?

I am using Azure cosmos db with the Mongodb API. Also i am using mongoose to create schemas and create new documents in the database. I am also using Node.js.
At this point I am considering using a One-to-Many relationship with embedded documents.
The data structure is like this :
{
"_id" : "locality1",
"_type" : "Locality",
"name" : "Wallmart",
"subsectionList" : [
{
"_id" : "subsection1",
"_type" : "SubSection",
"name" : "First floor",
"sensorList" : [
{
"_id" : "sensor1",
"_type" : "Sensor",
"placement" : "In the hallway"
},
{
"_id" : "sensor2",
"_type" : "Sensor",
"placement" : "In the ceiling"
}
]
},
{
"_id" : "subsection2",
"_type" : "SubSection",
"name" : "Second floor",
"sensorList" : [ ],
}
],
}
I want to retrieve ONLY the "sensor1"-object, not anything from the parent.
Using querying i am only able to retrieve the entire "locality1"-object, with all its underlying subsections and sensors. On a larger scale that is an unnecessary large amount of data.
Here is my query so far.
Locality.find().where('subsectionList.sensorList._id').equals("sensor1").then(doc => {
console.log(doc)
})
I appreciate any tips! :)
Based on my test, i can't get rid of the _id property anyway even though i followed the parameters which is mentioned here.
Locality.find({},'subsectionList', function (err, locas)
The above query still return the results including _id property.(It seems a default item)
I get a workaround from this blog that you could loop the array to filter your desired columns.
var mongoose = require('mongoose');
var COSMOSDB_CONNSTR= "mongodb://***.documents.azure.com:10255/db";
var COSMODDB_USER= "***";
var COSMOSDB_PASSWORD= "***";
mongoose.connect(COSMOSDB_CONNSTR+"?ssl=true&replicaSet=globaldb", {
auth: {
user: COSMODDB_USER,
password: COSMOSDB_PASSWORD
}
}).then(() => console.log('Connection to CosmosDB successful'))
.catch((err) => console.error(err));
const Locality = mongoose.model('Locality', new mongoose.Schema({
_id: String,
subsectionList: [{
sensorList: [{
_id: String,
_type: String,
placement: String
}]
}]
}));
Locality.find({},'subsectionList', function (err, locas) {
if (err) return handleError(err);
var returnArray = [];
for(var i = 0; i<locas.length;i++){
for(var j = 0; j<locas[i].subsectionList.length;j++){
for(var k = 0; k<locas[i].subsectionList[j].sensorList.length;k++){
if(locas[i].subsectionList[j].sensorList[k]._id == 'sensor1')
returnArray.push(locas[i].subsectionList[j].sensorList[k]);
}
}
}
console.log(returnArray);
});

$unwind nested document and $match

I have a nested document which looks like:
var User = new Schema({
id: String,
position: [{
title: String,
applied:[{
candidate_id: String,
name: String
}],
}],
What I am looking to do is return all of the 'applied' subdocuments which match a certain 'candidate_id'
What I have so far:
app.get('/applied', function(req, res){
var position = "58dc2bd4e7208a3ea143959e";
User.aggregate(
{$unwind : "$position"},
{$unwind : "$position.applied"},
{$match:{'position.applied.candidate_id': position}}).exec(function (err, result) {
console.log(result);
});
res.render('applied', { title: 'applied',layout:'candidate'});
});
I have another function which returns all the positions that match, and that code works:
app.post('/search', function (req, res) {
var position = new RegExp(req.body.position, 'i');
var location = new RegExp(req.body.location, 'i');
User.aggregate(
{$unwind : "$position"},
{$match:{'position.title': position,'position.location':location}}).exec(function (err, result) {
console.log(result);
res.send({ results: result });
});
});
So basically I am struggling with getting a sub-sub-document. Any idea where I'm going wrong?
Sample data:
{
"_id" : ObjectId("58c2871414cd3d209abf5fc9"),
"position" : [
{
"_id" : ObjectId("58d6b7e11e793c9a506ffe8f"),
"title" : "Software Engineer",
"applied" : [
{
"candidate_id" : "58d153e97e3317291gd80087",
"name" : "Sample user"
},
{
"candidate_id" : "58d153e97e3317291fd99001",
"name" : "Sample User2"
}
]
},
{
"_id" : ObjectId("58c2871414cd3d209abf5fc0"),
"title" : "Software Engineer",
}
],
}
What is going on above is there 2 positions, one of which (first entry) has 2 applied candidates, What I need to do is return the nested object if it matches the mongoose query.
Your code seems fine to me I have implemented same and it works for me only possible issue can be that your position="58dc2bd4e7208a3ea143959e" it might be talking it as a string just convert it to objectId by using the following code and check it should work for you.
var mongoose = require('mongoose');
var position = mongoose.Types.ObjectId("58dc2bd4e7208a3ea143959e");
User.aggregate(
{$unwind : "$position"},
{$unwind : "$position.applied"},
{$match:{'position.applied.candidate_id': position}}).exec(function (err, result) {
console.log(result);
});
res.render('applied', { title: 'applied',layout:'candidate'});
});

mongodb deep update - mongoose .id() causing performance issue

mongoose level collection schema
{
sublevel: [{
"deeplevel": [{
}],
"deeplevel2": [{
}],
}]
}
//routes.js
dlDoc = { "dl1": "dl1" };
db.levels.update({ _id: ObjectId(levelId), "sublevel._id": ObjectId(sublevelId) }, { $push: { "sublevel.$.deeplevel1": dlDoc } }, function (err, updatedDoc) {
if (updatedDoc) {
res.json({ "status": 1 });
res.end();
//calling external apis to update more
result = externalApiResult();
db.levels.findById(level._id, 'sublevel._id sublevel.deeplevel1', function (err, levelFound) {
levelFound.sublevel.id(sublevelId).deeplevel.id(dlDoc._id)['result'] = result;
levelFound.save(function (err, savedDoc) {
});
})
}
});
I need to create and update the level collection's deeplevel1. in my case, the deeplevel1 will be inserted more than 2000 sub docs per day. when i want to update using mongoose .id(deepLevelId) function it is causing me performance issues in the server. is there any way to find the position of deeplevel document inserted once i update the level collection?. so that i can use the position in the update query. And please tell me a best way to update my deeplevel subdocuments without causing performance issues and works fast. thanks in advance.
db.collection.findOne() will be like this.
{
"_id" : ObjectId("563b35d1f07cc9d80a26436b"),
"name":"name",
sublevel:[{
"_id" : ObjectId("569bede3c717b670097519c7"),
"name" : "name",
"deeplevel2" : [{
"_id" : ObjectId("569c559329cc880c18989349"),
"logTime" : new Date("1/18/2016 03:30:48"),
"areaId" : ObjectId("568a6129de552e7dba98d547"),
}, {
"_id" : ObjectId("569c561929cc880c18989354"),
"logTime" : new Date("1/18/2016 03:30:48"),
"areaId" : ObjectId("568a6129de552e7dba98d547"),
}, {
"_id" : ObjectId("569c5945626ffb680e4512e9"),
"logTime" : new Date("1/18/2016 03:30:48"),
"areaId" : ObjectId("568a6129de552e7dba98d547"),
}, {
"_id" : ObjectId("569c594d626ffb680e4512eb"),
"logTime" : new Date("1/18/2016 03:30:48"),
"areaId" : ObjectId("568a6129de552e7dba98d547"),
}
]
}]
}

Using aggregations to group elements of my array which are present in mongoDB but returning nothing?

Hello all i have an array of items now i want to know which of them are present in mongoDB now for that i read that i should use aggregations now i am using aggregations but it is not returning anything can anyone please point out what am i doing wrong below is my query given
userfavouritemodel.aggregate([
{ "$match": { "offers": {"$in": my_array}, "mobile_no":"1234567890" } },
{ $unwind: "$offers" },
{ "$group" : { "_id":"$_id","matched_elements":{ "$addToSet": "$offers" }}}
], function (err, result) {
if (err) {
console.log(err);
return;
}
console.log('user favourites');
console.log(result);
});
UPDATE- Example of documents in my database
{ "_id" : "566d6add9384223014ebcf43" , "mobile_no" : "1234567890" , "total_offers" : 4 , "offers" : [ "565ae5d8fff110dc18718b7c" , "565ae479fff110dc18718b7a" , "565ae479fff110dc18718b7a" , "5644a9339bf660501f15254e"]}
Here you go, this will return the offers that matches the mobile number and the offers within the array:
db.collection.aggregate([
{$match:{mobile_no:"1234567890"}},
{$project:{_id:0, offers:1}},
{$unwind:"$offers"},
{$match:{offers:{$in:["565ae479fff110dc18718b7a", "565ae5d8fff110dc18718b7c"]}}}]);

render view in SailsJS after mongodb forEach loop query

I have 2 collections name "Keywords" and "Company", I use MongoDB aggregate framework to retrieve related object._id from "Keywords" collection base on keywords user key in.
After i got the object._id from keywords collection, i want to query and compile a final complete docs from Company collection using the object._id.
I stuck on the part where res.view() run first before the result[] collect all the docs from Company collection.
I need to help to turn my code to Synchronous approach. Please help me. Below are what i did.
Sample of doc from "Keywords" Collection
{
"_id": ObjectID("52ac7130bd40d00a7beb7a29"),
"keyword": "Sunshine",
"object": [
{
"_id": ObjectID("528443ce751fc9b805d640ad"),
"type": "companyName"
}
]
}
Sample of doc from "Company" Collection
{
"_id": ObjectID("528443ce751fc9b805d640ad"),
"name": "Sunshine Plaza",
...
...
...
}
SearchController in SailsJS
var keyWords = req.query.q,
searchKeywords = keyWords.toLowerCase().replace(/[^\w\s]/gi, ' ').split(' '), //For example user key in "Sunshine Plaza"
results = [];
Keyword.native(function(err,collection){
collection.aggregate([
{
$project : {
'_id' : 0,
'keyword' : 1,
'object' : 1
}
}, {
$match : {
'keyword' : {
'$in' : searchKeywords
}
}
} , {
$unwind : '$object'
} , {
$group : {
_id : '$object._id',
count : {
$sum : 1
}
}
} , {
$sort : {
count: -1
}
} , {
$skip : 0
} , {
$limit : 10
}
], function (err, docs){
docs.forEach(function (doc, i){
Company.findOne({
'_id' : doc._id
},function(err,docs){
results.push(docs);
});
});
});
});
res.view({
key : keyWords,
results : results,
layout: "layouts/search"
});
What you're missing is that this isn't blocking code.
So the following
setTimeout(function() {
console.log('hi');
}, 2000);
console.log('bob');
Bob would happen first. Then hi. This is because it doesn't stop.
So you should rewrite this part of your code:
function (err, docs){
docs.forEach(function (doc, i){
Company.findOne({
'_id' : doc._id
},function(err,docs){
results.push(docs);
});
});
});
});
res.view({
key : keyWords,
results : results,
layout: "layouts/search"
});
To something like the following:
function (err, docs){
docs.forEach(function (doc, i){
Company.findOne({
'_id' : doc._id
},function(err,docs){
results.push(docs);
});
}, myFunction());
});
});
function myFunction() {
res.view({key : keywords, results : results, layout: "layouts/search" });
}

Resources