Waterline: Sum/Avg/Mix/Max of populated values in waterline - javascript

Please see the example:
User Object:
{
name: 'Mike',
age: 16,
createdAt: Wed Feb 12 2014 18:06:50 GMT-0600 (CST),
updatedAt: Wed Feb 12 2014 19:30:54 GMT-0600 (CST),
id: 7
}
Pet Objects associated with the user Mike
{
name: 'Scooby',
color: 'pink',
petAge: 2
id: 1,
createdAt: Wed Feb 12 2014 18:06:50 GMT-0600 (CST),
updatedAt: Wed Feb 12 2014 18:06:50 GMT-0600 (CST)
}
{
name: 'Alpha',
color: 'red',
petAge: 5
id: 2,
createdAt: Wed Feb 12 2014 18:16:50 GMT-0600 (CST),
updatedAt: Wed Feb 12 2014 18:16:50 GMT-0600 (CST)
}
I want to get sum of 'petAge' for pets of Mike. I was trying the below query, but it did not work.
User.find({name:'Mike'})
.populate('pets')
.sum('pets.petAge')
.exec(function(e,r){
});
I want to understand if getting sum of petAge is possible or not. (sum('pets.petAge')).

What you can do is use the sum function on the Pets model like this.
Pets.sum('petAge').where({user: "UserID"}).exec(function (e,r) {
//do what you want here
});
here UserID is the id of the user.

Related

How do I group together identical items when mapping over an array of objects?

Given the following array of gigs:
const gigs = [
{
name: ' sat gig 1',
date: 'Sat Dec 10 2022'
},
{
name: ' sat gig 2',
date: 'Sat Dec 10 2022'
},
{
name: ' sun gig 1',
date: 'Sun Dec 11 2022'
},
{
name: ' sun gig 2',
date: 'Sun Dec 11 2022'
},
]
How do I map over it and render the gigs, but grouped by the gig date? I've included the desired output as follows, as well as my own attempt to solve this. I'd prefer to not use lodash.
Sat Dec 10
sat gig 1
sat gig 2
Sun Dec 11
sun gig 1
sun gig 2
Here's my attempt so far:
const gigs = [
{
name: ' sat gig 1',
date: '2022-12-10'
},
{
name: ' sat gig 2',
date: '2022-12-10'
},
{
name: ' sun gig 1',
date: '2022-12-11'
},
{
name: ' sun gig 2',
date: '2022-12-11'
},
]
const gigArray =[]
gigs.map(gig => {
const gigDate = new Date(gig.date)
const gigDateString = gigDate.toString().slice(0,15) //gives date in form 'Sun Dec 11 2022'
gigArray.push({date:gigDateString,name:gig.name})
})
const groupedObj = gigArray.reduce(
(prev, current) => ({
...prev,
[current]: [...(prev[current] || []), current],
}),
{}
);
const groupedObjToArr = Object.values(groupedObj);
Here's a reduce solution that creates an object with the dates as the keys:
const gigs=[{name:"sat gig 1",date:"Sat Dec 10 2022"},{name:"sat gig 2",date:"Sat Dec 10 2022"},{name:"sun gig 1",date:"Sun Dec 11 2022"},{name:"sun gig 2",date:"Sun Dec 11 2022"}];
const result = gigs.reduce((acc, curr) => {
if (acc[curr.date]) {
acc[curr.date].push(curr)
} else {
acc[curr.date] = [curr]
}
return acc;
}, {})
console.log(result)
From there, generating the output is simple:
const gigs=[{name:"sat gig 1",date:"Sat Dec 10 2022"},{name:"sat gig 2",date:"Sat Dec 10 2022"},{name:"sun gig 1",date:"Sun Dec 11 2022"},{name:"sun gig 2",date:"Sun Dec 11 2022"}];
const result = gigs.reduce((acc, curr) => {
if (acc[curr.date]) {
acc[curr.date].push(curr)
} else {
acc[curr.date] = [curr]
}
return acc;
}, {})
Object.keys(result).forEach(key => {
console.log(key)
result[key].forEach(val => console.log(val))
})

Array groupby and count

I am trying to get day wise count from below data
example:
{ 'Tue Oct 01 2019': 3, 'Tue Oct 02 2019': 1 }
But I'm not getting the expected result from the below code.
const data = [ { Date: 'Tue Oct 01 2019' },{ Date: 'Tue Oct 01 2019' },{ Date: 'Tue Oct 01 2019' }, { Date: 'Tue Oct 02 2019' } ];
const result = data.reduce((total, value) => {
total[value] = (total[value] || 0) + 1;
return total;
}, {});
console.log(result);
If I understood you correctly, what you want is to group and get count:
const data = [
{ Date: 'Tue Oct 01 2019' },
{ Date: 'Tue Oct 01 2019' },
{ Date: 'Tue Oct 01 2019' },
{ Date: 'Tue Oct 02 2019' }
];
const result = data.reduce((total, {Date}) => {
total[Date] = (total[Date] || 0) + 1;
return total;
}, {});
console.log(result);
value is an Object, use value.Date instead of just value :
const data = [
{ Date: "Tue Oct 01 2019" },
{ Date: "Tue Oct 01 2019" },
{ Date: "Tue Oct 01 2019" },
{ Date: "Tue Oct 02 2019" }
];
const result = data.reduce((total, value) => {
total[value.Date] = (total[value.Date] || 0) + 1;
return total;
}, {});
console.log(result);

Object.values on a realmjs object returns an empty array

Description
I'm trying to convert my realm object to an array as can be seen below in the history method.
class RealmStore {
#observable symptoms = {};
#observable meals = {};
#computed get history(){
return [...Object.values(this.symptoms), ...Object.values(this.meals)];
}
//More methods to populate this.symptoms and this.meals
}
When I log this.symptoms I get the following output in my terminal:
{
'0': {
date: Fri Jun 29 2018 15: 56: 48 GMT + 0200(CEST),
name: 'Regurgitation',
value: 1
},
'1': {
date: Fri Jun 29 2018 15: 58: 09 GMT + 0200(CEST),
name: 'Belching',
value: 1
},
'2': {
date: Fri Jun 29 2018 16: 10: 39 GMT + 0200(CEST),
name: 'Heartburn',
value: 2
},
'3': {
date: Fri Jun 29 2018 23: 30: 36 GMT + 0200(CEST),
name: 'Heartburn',
value: 1
}
}
When I log Object.keys(this.symptoms) I get the following in my terminal:
[ '0', '1', '2', '3' ]
When I log Object.values(this.symptoms) I get the following in my terminal:
[]
This is the only way that this works:
const values = [];
for(let prop in this.symptoms){
if(this.symptoms.hasOwnProperty(prop)){
values.push(this.symptoms[prop])
}
}
console.log(values);
This logs the following in my terminal:
[{
date: Fri Jun 29 2018 15: 56: 48 GMT + 0200(CEST),
name: 'Regurgitation',
value: 1
},
{
date: Fri Jun 29 2018 15: 58: 09 GMT + 0200(CEST),
name: 'Belching',
value: 1
},
{
date: Fri Jun 29 2018 16: 10: 39 GMT + 0200(CEST),
name: 'Heartburn',
value: 2
},
{
date: Fri Jun 29 2018 23: 30: 36 GMT + 0200(CEST),
name: 'Heartburn',
value: 1
}
]
Question:
What is causing the realmjs object to be unable to return an array of values?
Currently unsure as to why Object.values() does not work. I went ahead and used this alternative, which according to some posts may cause performance issues.
Array.from(this.symptoms);

How to count occurrences in an array of objects by date

I'm searching a powerful solution in TypeScript or JavaScript to count occurrences in an array of object. I'd like to do that by Date. (I need it to create some charts)
For example, i have this array :
var arr = [
{date: Wed Jan 20 2016
type: "Apples"},
{date: Mon Feb 29 2016
type: "Peaches"},
{date: Thu Mar 31 2016
type: "Apples"},
{date: Fri Apr 22 2016
type: "Apples"},
{date: Fri Apr 22 2016
type: "Apples"},
{date: Fri Apr 22 2016
type: "Apples"},
{date: Fri Apr 22 2016
type: "Strawberries"}
]
The result I would like to have is the next one :
var arr2 = [
{date: Wed Jan 20 2016
type: ["Apples", 1]},
{date: Mon Feb 29 2016
type: ["Peaches",1]},
{date: Thu Mar 31 2016
type: ["Apples",1]},
{date: Fri Apr 22 2016
type: ["Apples",3],["Strawberries",1]}
]
I don't know why, but I can't find a good solution, I'm working on it during some days...
If anybody knows a trick, a function, or something else?
try this
First create a map
var map = {}; arr.forEach(function(val){
map[val.date] = map[val.date] || {};
map[val.date][val.type] = map[val.date][val.type] || 0;
map[val.date][val.type]++;
});
Now get the output
var output = Object.keys(map).map(function(key){
var tmpArr = [];
for(var type in map[key])
{
tmpArr.push( [ type, map[key][type] ] )
}
return { date : key, type: tmpArr };
})
DEMO
var arr = [
{date: "Wed Jan 20 2016",
type: "Apples"},
{date: "Mon Feb 29 2016",
type: "Peaches"},
{date: "Thu Mar 31 2016",
type: "Apples"},
{date: "Fri Apr 22 2016" ,
type: "Apples"},
{date: "Fri Apr 22 2016" ,
type: "Apples"},
{date: "Fri Apr 22 2016" ,
type: "Apples"},
{date: "Fri Apr 22 2016" ,
type: "Strawberries"}
]
var map = {}; arr.forEach(function(val){
map[val.date] = map[val.date] || {};
map[val.date][val.type] = map[val.date][val.type] || 0;
map[val.date][val.type]++;
});
var output = Object.keys(map).map(function(key){
var tmpArr = [];
for(var type in map[key])
{
tmpArr.push( [ type, map[key][type] ] )
}
return { date : key, type: tmpArr };
})
document.body.innerHTML += JSON.stringify(output,0,4);
should work like this:
var x = new Date().getTime(),
filtered = arr.filter( function (obj) { return obj.date.getTime() >= x }),
occurenceCount = filtered.length;
I use getTime() to convert the dates to integer, since I had odd behaviour comparing Date objects bevor. arr2 would contain all dates after x (in this exampale NOW) and count would return the number of elements contained in arr2.
With a proper date format like here with ISO date, and a temporary object, you could use a Array#forEach loop and return the wanted result. It works in a single loop.
var array = [{ date: '2016-01-20', type: "Apples" }, { date: '2016-02-29', type: "Peaches" }, { date: '2016-03-31', type: "Apples" }, { date: '2016-04-22', type: "Apples" }, { date: '2016-04-22', type: "Apples" }, { date: '2016-04-22', type: "Apples" }, { date: '2016-04-22', type: "Strawberries" }],
grouped = [];
array.forEach(function (a) {
var key = a.date + '|' + a.type;
if (!this[a.date]) {
this[a.date] = { date: a.date, type: [] };;
grouped.push(this[a.date]);
}
if (!this[key]) {
this[key] = [a.type, 0];
this[a.date].type.push(this[key]);
}
this[key][1]++;
}, Object.create(null));
document.write('<pre>' + JSON.stringify(grouped, 0, 4) + '</pre>');
Filter the array and check the date in the filter function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
function findItemsByDate(value) {
// find if an item already exists with the date index
var dateIndex = arr2.findIndex(findDateIndex);
// create an array or use the existing one based on result
if(dateIndex === -1){
var dateArray = []
}else{
dateArray = arr2[dateIndex];
}
// find the type object based on the input type and add to it, or create a new one.
if(dateArray.type.hasOwnProperty(value.type)){
dateArray.type[value.type] += 1;
}else{
dateArray.type[value.type] = 1;
}
}
// utility function to see if an item already exists in the new array with the key for the date.
function findDateIndex(item, index, arr){
if(item.date = "Thu Mar 31 2016"){
alert("Has Data")
return index;
}
return -1;
}
This will return a slightly different, but more managable result than you are looking for.
var arr2 = [
{date: "Wed Jan 20 2016", type: ["Apples", 1]},
{date: "Mon Feb 29 2016",type: ["Peaches",1]},
{date: "Thu Mar 31 2016", type: ["Apples",1]},
{date: "Fri Apr 22 2016", type: {"Apples":3,"Strawberries":1}}
]

Dates not updating properly in nodeJS

Following is my code which is not properly updating the dates-
exports.saveWeekAvailability = function(req, res){
console.log("-- SAVE WEEK AVAILABILITY --");
weekData = req.body;
weekData.sort(function(a, b){ var dateA = new Date(a.currDate); var dateB = new Date(b.currDate); return dateA-dateB;});
var x=0;
var resultArr = [];
for(var i=0; i< weekData.length; i++) {
(function(i) {
Availability.findOne({employee_id:weekData[i].employee_id,currDate:weekData[i].currDate},function(err,response){
console.log("============= RESPONSE ==============");
console.log("I: "+i);
console.log("X: "+x);
if ( null !== response ) {
response.is_morning_scheduled = weekData[x].is_morning_scheduled;
response.is_night_scheduled = weekData[x].is_night_scheduled;
console.log("-----------IN NULL IN NULL IN NULL---------------");
console.log(response);
// CODE TO UPDATE
}
else{
addAvailability(x);
}
x++;
})
})(i);
}
};
Scenario -
For dates Tue, 07 Oct 2014 18:30:00 GMT & Wed, 08 Oct 2014 18:30:00 GMT my morning schedule is set true like - is_morning_scheduled: true.
But in Response you can check it is taking true for currDate: Sat Oct 11 2014 00:00:00 GMT+0530 (IST) & currDate: Sat Oct 07 2014 00:00:00 GMT+0530 (IST) date.
Let me know what I am doing wrong here with the concept.
weekData -
[
{
currDate: 'Sat, 04 Oct 2014 18:30:00 GMT',
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: '53d89f0e5bfa37320be2d1f7',
},
{
currDate: 'Sun, 05 Oct 2014 18:30:00 GMT',
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: '53d89f0e5bfa37320be2d1f7',
},
{
currDate: 'Mon, 06 Oct 2014 18:30:00 GMT',
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: '53d89f0e5bfa37320be2d1f7',
},
{
currDate: 'Tue, 07 Oct 2014 18:30:00 GMT',
is_morning_scheduled: true,
is_night_scheduled: false,
employee_id: '53d89f0e5bfa37320be2d1f7',
},
{
currDate: 'Wed, 08 Oct 2014 18:30:00 GMT',
is_morning_scheduled: true,
is_night_scheduled: false,
employee_id: '53d89f0e5bfa37320be2d1f7',
},
{
currDate: 'Thu, 09 Oct 2014 18:30:00 GMT',
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: '53d89f0e5bfa37320be2d1f7',
},
{
currDate: 'Fri, 10 Oct 2014 18:30:00 GMT',
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: '53d89f0e5bfa37320be2d1f7',
}
]
Now after consoling the response I am getting the output like -
============= RESPONSE ==============
I: 0
X: 0
-----------IN NULL IN NULL IN NULL---------------
{
_id: 5424f0b679e352ff0ce0a556,
currDate: Sun Oct 05 2014 00:00:00 GMT+0530 (IST),
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: 53d89f0e5bfa37320be2d1f7,
__v: 0
}
============= RESPONSE ==============
I: 5
X: 1
-----------IN NULL IN NULL IN NULL---------------
{
_id: 5424f0b679e352ff0ce0a55b,
currDate: Fri Oct 10 2014 00:00:00 GMT+0530 (IST),
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: 53d89f0e5bfa37320be2d1f7,
__v: 0
}
============= RESPONSE ==============
I: 1
X: 2
-----------IN NULL IN NULL IN NULL---------------
{
_id: 5424f0b679e352ff0ce0a557,
currDate: Mon Oct 06 2014 00:00:00 GMT+0530 (IST),
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: 53d89f0e5bfa37320be2d1f7,
__v: 0
}
============= RESPONSE ==============
I: 6
X: 3
-----------IN NULL IN NULL IN NULL---------------
{
_id: 5424f0b679e352ff0ce0a55c,
currDate: Sat Oct 11 2014 00:00:00 GMT+0530 (IST),
is_morning_scheduled: true,
is_night_scheduled: false,
employee_id: 53d89f0e5bfa37320be2d1f7,
__v: 0,
}
============= RESPONSE ==============
I: 2
X: 4
-----------IN NULL IN NULL IN NULL---------------
{
_id: 5424f0b679e352ff0ce0a558,
currDate: Tue Oct 07 2014 00:00:00 GMT+0530 (IST),
is_morning_scheduled: true,
is_night_scheduled: false,
employee_id: 53d89f0e5bfa37320be2d1f7,
__v: 0
}
============= RESPONSE ==============
I: 3
X: 5
-----------IN NULL IN NULL IN NULL---------------
{
_id: 5424f0b679e352ff0ce0a559,
currDate: Wed Oct 08 2014 00:00:00 GMT+0530 (IST),
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: 53d89f0e5bfa37320be2d1f7,
__v: 0
}
============= RESPONSE ==============
I: 4
X: 6
-----------IN NULL IN NULL IN NULL---------------
{
_id: 5424f0b679e352ff0ce0a55a,
currDate: Thu Oct 09 2014 00:00:00 GMT+0530 (IST),
is_morning_scheduled: false,
is_night_scheduled: false,
employee_id: 53d89f0e5bfa37320be2d1f7,
__v: 0
}
The call to Availability.findOne(... uses an async callback and is thus not guaranteed to fire in the correct order, hence the reason you're seeing the i variable go up in a weird order (0, 5, 1, 6, 2, 3, 4) and is different from the x variable which increments in order (0, 1, 2, 3, 4, 5, 6).
Why do you even have the x variable, just use i instead since you're already wrapping it in a closure i.e:
Availability.findOne({
employee_id: weekData[i].employee_id,
currDate: weekData[i].currDate
},
function(err, response) {
console.log("============= RESPONSE ==============");
console.log("I: " + i);
if (null !== response) {
response.is_morning_scheduled = weekData[i].is_morning_scheduled;
response.is_night_scheduled = weekData[i].is_night_scheduled;
console.log("-----------IN NULL IN NULL IN NULL---------------");
console.log(response);
// CODE TO UPDATE
}
else {
addAvailability(i);
}
});

Categories

Resources