So, in MongoDB I've a variable dates that is an object with array of objects as values for each date(key). Example data:
"dates": {
"2021-08-30": [{
"country": "Germany",
"views": 1,
"tt": "",
"mobile": 0,
"desktop": 1
}, {
"country": "United States of America",
"views": 4,
"tt": "",
"mobile": 0,
"desktop": 4,
"states": {
"New York": {
"views": 2,
"mobile": 1,
"desktop": 1
},
"Florida": {
"views": 5,
"mobile": 3,
"desktop": 2
}
}
}],
"2021-08-31": [{
"country": "United States of America",
"views": 9,
"tt": "",
"mobile": 6,
"desktop": 3,
"states": {
"New York": {
"views": 6,
"mobile": 4,
"desktop": 2
},
"California": {
"views": 3,
"desktop": 1,
"mobile": 2
}
}
}]
}
}
Now I need to combine the data in one array based on date range, and if the Country is the same add those values together (not duplicate).
I've managed to do that, but the problem is that USA has states that I also want to be combined together based on the key. So if 2 dates, with country USA have a the same state (example is above New York) I want the information to be combined.
What I have so far:
useEffect(() => {
const analyticsFromDate = [];
let analyticsForDisplay = [];
for (var p in analytics.dates) {
if (analytics.dates.hasOwnProperty(p)) {
console.log(p);
if (
+new Date(p).setHours(0, 0, 0, 0) >=
+new Date(state[0].startDate.setHours(0, 0, 0, 0)) &&
+new Date(p).setHours(0, 0, 0, 0) <=
+new Date(state[0].endDate.setHours(0, 0, 0, 0))
) {
analyticsFromDate.push(analytics.dates[p]);
}
}
}
if (analyticsFromDate.length > 0) {
analyticsForDisplay = Array.from(
analyticsFromDate
.flat()
.reduce((acc, { views, desktop, mobile, states, ...r }) => {
const key = JSON.stringify(r);
const current = acc.get(key) || {
...r,
views: 0,
desktop: 0,
mobile: 0,
states: {},
};
return acc.set(key, {
...current,
views: current.views + views,
desktop: current.desktop + desktop,
mobile: current.mobile + mobile,
states: {...current.states, ...states},
});
}, new Map())
.values()
);
console.log(analyticsForDisplay);
setDisplayAnalytics(analyticsForDisplay);
} else {
setDisplayAnalytics([]);
}
}, [state, analytics]);
The above code works perfectly, except the states are just spread with the spread operator which doesn't increase the values it just replaces it if the keys are the same.
The Code above returns the following:
[{
"country": "Germany",
"views": 1,
"tt": "",
"mobile": 0,
"desktop": 1
}, {
"country": "United States of America",
"views": 13,
"tt": "",
"mobile": 6,
"desktop": 7,
"states": {
"New York": {
"views": 6,
"mobile": 4,
"desktop": 2
},
"California": {
"views": 3,
"desktop": 1,
"mobile": 2
},
"Florida": {
"views": 5,
"mobile": 3,
"desktop": 2
}
}
}]
I want it to return: (Look at New York)
[{
"country": "Germany",
"views": 1,
"tt": "",
"mobile": 0,
"desktop": 1
}, {
"country": "United States of America",
"views": 13,
"tt": "",
"mobile": 6,
"desktop": 7,
"states": {
"New York": {
"views": 8, // sum of both New York
"mobile": 5, // sum of both New York
"desktop": 3 // sum of both New York
},
"California": {
"views": 3,
"desktop": 1,
"mobile": 2
},
"Florida": {
"views": 5,
"mobile": 3,
"desktop": 2
}
}
}]
I've also tried in another useEffect to get the states, but it also doesn't sum the values of states.
Here is that code: (if the above is not possible maybe this is)
const statesFromDate = []
for (var p in dates) {
statesFromDate.push(dates[p]);
}
const statesForDisplay = statesFromDate.flat().filter(({
country
}) => country == "United States of America").reduce((acc, {
views,
desktop,
mobile,
states,
...r
}) => {
const key = JSON.stringify(r);
const current = acc || {
...r,
views: 0,
desktop: 0,
mobile: 0,
states: {},
};
const statesReturn = {...current.states, ...states}
return acc = key, {
...current,
views: current.views + views,
desktop: current.desktop + desktop,
mobile: current.mobile + mobile,
states: statesReturn,
};
})
Sandbox: https://codesandbox.io/s/small-microservice-qo9cq?file=/src/App.js