Aggregate returns empty array - node.js

Using mongoose's Model.aggregate() returns an empty array.
I've essentially copied the format as seen here.
var match = {};
var project = {};
project["_id"] = 0;
project["products.totalprice"] = 1;
project["line"] = "$products.closedate";
ThisCollection.aggregate([
{$match: match},
{$project: project},
{$group: {
_id: "$line"
}}
], function(err, docs){
console.log(docs); //!! Returning []
});
My schema is essentially a name and _id field with a nested array of products with totalprice, closedate and some other fields.
There are most certainly a plethora of entries (some 130,000 records). Can anyone spot an issue with this?

I have created this dummy data to represent a skeleton of your schema:
db.data.save({name:"a",products:{totalprice:1,closedate:1}})
db.data.save({name:"b",products:{totalprice:2,closedate:2}})
This query does return two records and is identical to yours when inserting the JSON string for the JavaScript variable project
ThisCollection.aggregate([{$match:{}},{$project:{"_id":0,"products.totalprice":1,line:"$products.closedate"}},{$group:{_id:"$line"}}])

Related

How to find documents from a mongoose schema, given an array of objects with IDs

I am trying to find some documents given an array of objects and inside each object, there is an id "courseId" which will be used to find the required documents from the schema with the same id.
Here is the array of objects:
courseIds = [
{"courseId":"638c139b147e2173163fd976",
"_id":"63906c07b9b09cd81e48480d"
},
{"courseId":"638c131a147e2173163fd96b",
"_id":"63908c9f1897b57aa6ece69f"
}]
and if the schema contains the following objects:
const courseSchema =
[{
"_id":"638c131a147e2173163fd96b",
"courseTitle":"Neural Networks",
"price":"5000",
"shortSummary":"Its a lovely course about NNs, Sequence Models.",
"subject":"Deep Learning"
},
{
"_id":"638c139b147e2173163fd976",
"courseTitle":"Graphics",
"price":"3000",
"shortSummary":"Its a lovely course about Projection, 2D & 3D Transformations.",
"subject":"Computer Graphics"
},
{
"_id":"638c131a147e9053163fd281",
"courseTitle":"Operating Systems",
"price":"4500",
"shortSummary":"Its a lovely course about Scheduling, learning about drivers and peripherals.",
"subject":"Hardware"
}]
What I want to do is I want to find/return only the courses from the courseSchema whose ids are present in the courseIds array, like here it would only return two courses:
{
"_id":"638c131a147e2173163fd96b",
"courseTitle":"Neural Networks",
"price":"5000",
"shortSummary":"Its a lovely course about NNs, Sequence Models.",
"subject":"Deep Learning"
},
{
"_id":"638c139b147e2173163fd976",
"courseTitle":"Graphics",
"price":"3000",
"shortSummary":"Its a lovely course about Projection, 2D & 3D Transformations.",
"subject":"Computer Graphics"
}
since their ids "_id" are present in the courseIds array ("courseId == _id").
I tried to do the following:
const docs = courseSchema.find().where('_id').in(courseIds);
and
const docs = courseSchema.find({ '_id': { $in: courseIds} });
and it always return an empty array (no matches).
Why doesn't it work?
courseIds id a array object, in order to match _id with $in the array must be of only _id like ["638c139b147e2173163fd976","638c131a147e2173163fd96b"].
for that you can make another array from courseIds array object and use that as in query with $in.
courseIds = [
{
"courseId":"638c139b147e2173163fd976",
"_id":"63906c07b9b09cd81e48480d"
},
{
"courseId":"638c131a147e2173163fd96b",
"_id":"63908c9f1897b57aa6ece69f"
}
] //Your courseIds array object
let onlyIds=[] // declaring array to store only _ids
for(let i=0;i<courseIds.length;i++){
if(!onlyIds.includes(courseIds[i].courseId)) //checking id exist in array, if not exist push _id to onlyIds aarray
onlyIds.push(courseIds[i].courseId); //push _id
}
console.log(courseId)//output=>["638c139b147e2173163fd976","638c131a147e2173163fd96b"]
const docs = courseSchema.find({ _id: { $in: onlyIds } }); //final query

How to search data in mongodb with dynamic fields using mongoose?

I've a node.js api in which user sends the required fields as an array to be fetched from the mongodb database. I need to find the data of that fields using Find query. I've written forEach statement to loop through that array and got the array elements. But when I try to get the results by inserting the array elements in the query, it doesn't giving the required results. Could any one please help me in resolving the issue by seeing the code below?
templateLevelGraphData: async function(tid,payload){
let err, templateData, respData = [], test, currentValue;
[err,templateData] = await to(Template.findById(tid));
var templateId = templateData.templateId;
payload.variables.forEach(async data=>{
console.log(data); //data has the array elements like variables=["humidity"]
[err, currentValue] = await to(mongoose.connection.db.collection(templateId).find({},{data:1}).sort({"entryDayTime":-1}).limit(1).toArray());
console.log(currentValue);
});
return "success";
}
The expected output is,
[ { humidity: 36 } ]
But I'm getting only _id like,
[ { _id: 5dce3a2df89ab63ee4d95495 } ]
I think data is not applying in the query. But I'm printing the data in the console where it's giving the correct results by displaying the array elements like, humidity. What I need to do to make it work?
When you are passing {data: 1} you are passing an array where is expecting name of column.
You have to create an object where the keys are going to be the elements of the array and set them to 1.
const projection = data.reduce((a,b) => (a[b]=1, a), {});
[...] .find({}, projection) [...]
Actually I got the solution.
for(let i=0;i<payload.variables.length;i++){
var test = '{"'+ payload.variables[i] +'":1,"_id":0}';
var query = JSON.parse(test);
[err, currentValue] = await to(mongoose.connection.db.collection(templateId).find({"deviceId":deviceId},query).sort({"entryDayTime":-1}).limit(1).toArray());
console.log(currentValue); //It's giving the solution
}

Mongoose find not match ids from array which passed

I'm stuck in mongoose query. I've an array of ids as input, I want to search that array of ids in a database for matching elements. It returns perfect result after using $in in find query.
Now, I want that Ids from an array which is not found in the database. what is the best way to do it?
Please try to comment it.
Template.find({
_ids : [
"as6d87as67da7s8d87a87", // available in database
"as6dasd8sa9d8a9a9s8d7", // not-available in database
"6756asd5as6dsadghasd3", // available in database
]
}, function(err, result){
// Need result as "as6dasd8sa9d8a9a9s8d7", which is not matched. or in object.
// Can we do with `aggregate` query?
});
I think this makes what you want
var _ids = [
"as6d87as67da7s8d87a87",
"as6dasd8sa9d8a9a9s8d7",
"6756asd5as6dsadghasd3"
];
Template.find({
_ids : _ids
}, function(err, result){
var filteredResult = _ids.filter(currentId => !result.some(item => item._id.toString() == currentId));
});
Answer by David will work. The idea here is to compare _ids array with the _ids in the result and return the missing ones. Adding more code just for understanding purposes:
Push _id of result into a new array
Compare _ids and the new array to return missing elements
var resIDs = new Array();
for (var i = 0; i < result.length; i++) {
resIDs.push(result[i]._id.toString());
}
var resultFiltered =
_ids.filter(function (v) {
return !resIDs.includes(v.toString());
})

db.collection.find() is ignoring query criteria

I have the following node.js code interacting with mongo:
var lowrange = 1;
var collection = db.get('postings');
collection.find({},{postid: { $gt: lowrange }, limit: 10, sort: {_id: -1}},function(e,docs){
res.json(docs);
});
I am using this to list the contents of the collection 'postings' via a json response. The limit: 10 and sort criteria work as expected. The postid: { $gt: lowrange } section seems to be ignored.
In other words, I am getting all records, even those that are less than the var lowrange. Why is this?
Edit:
Then what is the correct syntax? This produces no results (I assure you there are documents with a post id greater than 1):
collection.find({postid: { $gt: 1 }}, function(e,docs){
res.json(docs);
});
and how do you use limit/sort when you have a function as a param of find? The following errors:
collection.find({postid: { $gt: 1 }}, function(e,docs){
res.json(docs);
}).limit(10).sort( {_id: -1});
The first parameter of find is the query document. Yours is empty ({}).
In fact, I'm not sure where you've seen that syntax, with limit and sort as field names.
See Read Operations Overview.

Node, MongoDB (mongoose) distinct count

I have a collection with multiple documents and every one of them has and 'eID' field that is not unique. I want to get the count for all the distinct 'eID'.
Example: if there are 5 documents with the 'eID' = ObjectID(123) and 2 documents with 'eID' = ObjectID(321) I want to output something like:
{
ObjectID(123): 5,
ObjectID(321): 2
}
I don't know if that can be done in the same query but after knowing what are the most ocurring eID's I want to fetch the referenced documents using the ObjectID
Mongoose version 3.8.8
$status is the specific field of collection that i need to count distinct number of element.
var agg = [
{$group: {
_id: "$status",
total: {$sum: 1}
}}
];
model.Site.aggregate(agg, function(err, logs){
if (err) { return res.json(err); }
return res.json(logs);
});
//output
[
{
"_id": "plan",
"total": 3
},
{
"_id": "complete",
"total": 4
},
{
"_id": "hault",
"total": 2
},
{
"_id": "incomplete",
"total": 4
}
]
This answer is not in terms of how this query can be written via mongoose, but I am familiar with the nodejs MongoClient class if you have further questions regarding implementation.
The best (most optimal) way I can think of doing this is to use mapReduce or aggregation on your database. The closest thing to a single command would be the distinct command, which can be invoked on collections, but this will only give you an array of distinct values for the eID key.
See here: http://docs.mongodb.org/manual/core/map-reduce/
For your specific problem, you will want your map and reduce functions roughly as follows:
var map = function() {
var value = 1;
emit(this.eID, value);
};
var reduce = function(key, values) {
var result = 0;
for(var i=-1;++i<values.length;){
var value = values[i];
result += value;
};
return result;
};
There might be an easier way to do this using the aggregation pipeline (I would post the link but I don't have enough reputation).
I also found the mapReduce command for mongoose: http://mongoosejs.com/docs/api.html#model_Model.mapReduce

Resources