Count every distinct values from mongodb then render to amcharts - angularjs

I'm trying to get the count of every distinct values from my mongodb, So far I can get the distinct values and count it.
How can I do this:
City Count
Pasig 22
Manila 12
Pasay 11
Sample document:
_id:5c1ca770385b472018874073
blood_product_donated:"Whole Blood"
branch:"Pasay"
deferral_type:"none"
deferral_date:"none"
So far here is what I did:
api.js
router.get('/blooddonationpie', function(req, res) {
Blooddonation.distinct('branch',function(err, branch) {
res.json({ success: true, branch: branch });
console.log(branch);
});
});
controller
angular.module('blooddonationControllers', [])
.controller('blooddonationCtrl', function(Blooddonation,$scope) {
var app = this;
function getChart() {
Blooddonation.getChart().then(function(data) {
app.branch = data.data.branch;
initChart();
});
}
function initChart() {
var data_series = [];
for(let key in app.branch) {
data_series.push({
"donor": app.branch[key],
"count": 501.9
});
}
var chart = AmCharts.makeChart( "chartdiv", {
"type": "pie",
"theme": "none",
"dataProvider": data_series,
"valueField": "count",
"titleField": "donor",
"balloon":{
"fixedPosition":true
},
"export": {
"enabled": true
}
});
}
This is the wrong output:
How can I get the count for each distinct values? Example Pasig: 21, Pasay: 22 etc.

You need to $group aggregation to get the count of each branches
db.col.aggregate([{$group: {_id : "$branch" , count :{$sum:1}}}])

Related

How to find out number of elements in MongoDB array?

My collection of products consists of _id, product/title, product/price and reviews. Reviews is an array with all reviews for that specific product. I am trying to print out 10 products with the largest number of reviews but can't find the right solution.
This is what I tried so far:
var mapFunction = function() {
emit(this._id, {
product: this,
count_reviews: this.reviews.length
});
};
var reduceFunction = function(key, values) {
var count = 0;
var product;
values.forEach(function(value) {
count += value.count_reviews;
product = value.product
});
return { count_reviews: count, product: product};
};
db.products.mapReduce(mapFunction, reduceFunction, {
out: { inline: 1},
query: {},
sort: { count_reviews: -1 },
limit: 10
});
When I run this code it prints out 10 elements, but not with the largest number of reviews.
I wouldn't use mapReduce (unless you're on a version so old you have to)
I'd use an aggregation, if you have strict data - you can omit the $match, if you have "strictish" data (e.g., it's an array or missing) you can use a simpler match: { reviews: { $exists: true } }
db.products.aggregate([
{
$match: {
"value.reviews": { $type: "array" }
}
},
{
$set: { review_count: { $size: "$value.reviews" } }
},
{
$sort: { review_count: -1 },
},
{
$limit: 10
}
])

Trying to call a variable from JSON

New to AngularJS so apologies if my terminology isn't correct. I am trying to call a value that is in my JSON body, however the difference is that it's also inside another body called student.
{
"id": 3,
"teacherName": "N/A",
"students": [
{
"student": "n/a"
}
],
"status": "ALIVE"
}
My JS code consists of the following:
$scope.table = function () {
SpringDataRestService.get(
{
collection: "school",
resource: $scope.teacherSelected.id
},
function (response) {
var students= [];
for (var j = 0; j < response.students.length; j++) {
var entitlement= {
student: response[j].student,
};
students.push(entitlement);
}
$log.info(JSON.stringify(entitlement))
$scope.tableOptions = new NgTableParams({}, {
dataset: students,
counts: []
});
}
);
};
There is an error in for loop. Instead of:
student: response[j].student
you need to use this:
student: response.students[j].student
Check this working demo: DEMO

MongoDB : Complex Arrary field

{
"_id" : ObjectId("58d9084841a6168234689aee"),
"ID" : "01",
"data" : {
"Type1" : {
"value" : "ABC",
"timestamp" : "2017-03-20 16:01:01"
},
"Type2" : {
"value" : "ccc",
"timestamp" : "2017-03-20 16:01:01"
}
}
}
I want to get timestamp of each TYPE from mongodb using queryobject using nodejs.
How to get it,Please help.
var queryObject = url.parse(req.url,true).query;
var mdb = db.collection("HISTORY").find({{'timestamp':{"$gte":queryObject.fromdate,"$lt" : queryObject.todate}},{"ID":1});
Here is my node service:
function getHistory(req,res){
try{
var queryObject = url.parse(req.url,true).query;
var index=0, resultset = [];
var db1 = db.collection("HISTORY").find({$and : [{'data.Type1.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type2.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type3.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type4.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type5.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}}
]},{"Ino":1,"ID":1,"data":1});
db1.count(function(err, count) {
console.log("count" , count);
db1.each(function(err, doc) {
if(doc!=null){
var valdata=doc.alarms;
var fields = [];
var queryString ="SELECT field1,NAME FROM details c inner join locdetails l on c.loc_id=l.loc_id where no='"+doc.Ino+"' limit 1;";
var dtfield1 = null;
var dtfield2 = null;
connection.query(queryString, function(err,result){
index++;
if(err){
}else{
if(result.length>0)
{
dtfield1 = result[0].field1;
dtfield2 = result[0].NAME;
if(dtfield1!=null){
for (var x in valdata) {
var dt = new Date(valdata[x].timestamp).toISOString().replace(/T/, ' ').replace(/\..+/, '');
var compareDate = new Date(dt);
if(compareDate.getTime()>=fromDate.getTime()&&compareDate.getTime()<=toDate.getTime()){
resultset.push({"Name":dtfield1,"LName":dtfield2,"Ino":doc.Ino,"ID":doc.ID,"data":x,"datav":valdata[x].value,"Timestamp":valdata[x].timestamp});
}
if(index == count){
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.write(JSON.stringify(resultset));
res.end();
}
}} }}
});
} else {
}
});
});
}
catch (err) {
console.log("Exception -- ",err);
}
}
I want data should filter based on timestamp and same can be display in UI and download the displayed data.And also filter should be in UI like current day data and based on time filter also.
If you want search base on both Type1.timestamp and Type2.timestamp, you should use $and. you can change $and with $or if one matching one of them is enough
db.collection("HISTORY").find({
$and : [{'data.Type1.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type2.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}}
]
},
{ID:1}, function (err, res){
});
You can use aggregation to meet your requirements.
For your initial list which will only show the latest data values of each object, you can use the following pipeline -
[
{
$project:{
_id:1,
ID:1,
data:{ $objectToArray: "$data" }
}
},
{
$unwind:"$data"
},
{
$sort:{
"data.v.timestamp":-1
}
},
{
$group:{
_id:{
_id:"$_id",
ID:"$ID"
},
data:{
$first:"$data"
}
}
},
{
$addFields:{
data:["$data"]
}
},
{
$addFields:{
data:{ $arrayToObject: "$data" }
}
}
]
The result of the aggregation should give you an array of objects like this -
{
"_id" : ObjectId("5bc469c11f8e482416d6edb3"),
"ID" : "01",
"data" : {
"Type2" : {
"value" : "ccc",
"timestamp" : ISODate("2017-03-22T16:01:01.000+06:00")
}
}
}
As for filtering the collection to get documents with data properties that have timestamp values in the given range, the above pipeline can be modified to acquire it
[
{
$project:{
_id:1,
ID:1,
data:{ $objectToArray: "$data" }
}
},
{
$unwind:"$data"
},
{
$sort:{
"data.v.timestamp":-1
}
},
{
$match:{
"data.v.timestamp":{ $gt: "start date value", $lt: "end date value"}
}
},
{
$group:{
_id:{
_id:"$_id",
ID:"$ID"
},
data:{
$addToSet:"$data"
}
}
},
{
$project:{
_id:"$_id._id",
ID:"$_id.ID",
data:{ $arrayToObject: "$data" }
}
}
]
The result of this aggregation will produce array of objects similar to the one described above. But this time each document's data object will only have properties that match the timestamp condition.
Hope this helps. A final word of advice to you would be to rethink the schema design of the history collection. Because if simplistic date based queries are getting this difficult for you. You can only imagine what the future might hold for you with this design.

How to publish a collection based on a value of an array value

I have the following data structure in a Meteor app, I would like to create a publication based on the "modelo" value.
{
"_id": "BAnLur25298ytvMdT",
"numero": "97",
"lienzos": 100,
"fechaCorte": "2016-03-29T00:00:00.000Z",
"modelos": [
{
"modelo": "95",
"distribucion": 100
},
{
"modelo": "96",
"distribucion": 100
}
],
"tela": "Jackard"
}
For example :
Meteor.publish('ModelosCorte', function(id) {
return CortesGeneral.find({
modelos: id
});
});
But I want to publish for example all CortesGeneral that have a "modelo": "96" as a value
You need to use dot notation to specify that you want to search for 'modelos.modelo'. Give this a try:
Meteor.publish('ModelosCorte', function (id) {
check(id, String);
return CortesGeneral.find({ 'modelos.modelo': id });
});

Get specific data in mongodb nodejs

i'm working with nodejs server using mongoDB. Now i have a sample data:
{
"_id": ObjectId("555f1c0c7f4b820758b439b0"),
"user": "Guest1",
"friend": [{
"myfriend": "Guest2",
"info": []
}, {
"myfriend": "Guest3",
"info": []
}]
}
Now i want to put all "myfriend" into array, like this:
var listfriend = ["Guest2","Guest3"];
So how can i do it ?
Thank for read :)
Try using the map() method as follows:
var listfriend = db.names.findOne(
{"user" : "Guest1"},
{"_id": 0, "friend": 1}
).friend.map(function(obj){
return obj.myfriend;
});
console.log(listfriend); // ["Guest2","Guest3"]
Did you want to use the aggregation framework?
var aggregateFriends = function( db, callback)
{
db.collection('test').aggregate(
[
{ $unwind: "$friend" },
{ $group: { _id: "$user", friends: {$push: "$friend.myfriend" } } }
]
).toArray( function( err, result ) {
console.log(result);
db.close();
} );
};
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert')
var ObjectId = require('mongodb').ObjectID;
var url = 'mongodb://localhost:27017/test';
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
aggregateFriends( db, function() { db.close(); });
} );

Resources