In ArangoDB I want to group and sort notification data.
I have the following notification data sets
[
{id: 1, groupId: 1, text: 'Aoo', time: 23},
{id: 2, groupId: 2, text: 'Boo', time: 32},
{id: 3, groupId: 1, text: 'Coo', time: 45},
{id: 4, groupId: 3, text: 'Doo', time: 56},
{id: 5, groupId: 1, text: 'Eoo', time: 22},
{id: 6, groupId: 2, text: 'Foo', time: 23}
]
I want to group the notification by groupId and the recent notification group should appear on top.
Final result should be like this
[
{ groupId: 3, notifications: [{id: 4, groupId: 3, text: 'Doo', time: 56}],
{ groupId: 1, notification: [{id: 3, groupId: 1, text: 'Coo', time: 45}, {id: 1, groupId: 1, text: 'Aoo', time: 23}, {id: 5, groupId: 1, text: 'Eoo', time: 22}]},
{ groupId: 2, notifications: [{id: 2, groupId: 2, text: 'Boo', time: 32}, {id: 6, groupId: 2, text: 'Foo', time: 23}] }
]
Tried following AQL
FOR doc IN notificaion
SORT doc.time DESC
COLLECT groupId = doc.groupId INTO g
RETURN { groupId, notifications: g[*].doc }
Above query sorts the inner group elements but the outer groups are not sorted.
I'm struggling to construct an AQL for it. Any pointer will be helpful.
Thanks
Sort twice: once the set of documents collected - as you already do, then the collection:
FOR doc IN notification
SORT doc.time DESC
COLLECT groupId = doc.groupId INTO g
SORT g[*].doc.time DESC
RETURN { groupId, notifications: g[*].doc }
In my tests this yields the desired sequence:
[
{
"groupId": 3,
"notifications": [
{
"id": 4,
"groupId": 3,
"text": "Doo",
"time": 56
}
]
},
{
"groupId": 1,
"notifications": [
{
"id": 3,
"groupId": 1,
"text": "Coo",
"time": 45
},
{
"id": 1,
"groupId": 1,
"text": "Aoo",
"time": 23
},
{
"id": 5,
"groupId": 1,
"text": "Eoo",
"time": 22
}
]
},
{
"groupId": 2,
"notifications": [
{
"id": 2,
"groupId": 2,
"text": "Boo",
"time": 32
},
{
"id": 6,
"groupId": 2,
"text": "Foo",
"time": 23
}
]
}
]
Related
I have a collection A with data like
{
id: 2,
name: "test"
},
{
id: 4,
name: "test4"
}
and I have a second collection B with data like:
{
id: 444,
name: "a",
colA_id: 2
},
{
id: 555,
name: "b",
colA_id: 2
},
{
id: 555,
name: "c",
colA_id: 10
},
After I aggregate both collections, I want an output like:
{
id: 2,
name: "test",
list_of_b: {
{
id: 444,
name: "a",
colA_id: 2
},
{
id: 555,
name: "b",
colA_id: 2
},
}
}
I tried to merge them, but every time I only get one record of the database.
Its just a simple look up
The DB is
db={
"collA": [
{
id: 2,
name: "test"
},
{
id: 4,
name: "test4"
}
],
"collB": [
{
id: 444,
name: "a",
colA_id: 2
},
{
id: 555,
name: "b",
colA_id: 2
},
{
id: 555,
name: "c",
colA_id: 10
}
]
}
And the aggregation is
db.collA.aggregate([
{
"$lookup": {
"from": "collB",
"localField": "id",
"foreignField": "colA_id",
"as": "list_of_b"
}
}
])
Working Mongo playground
i'm fairly new to MongoDB and Mongoose and i'm working on a bug here. Apparently $sum is not working with a field whose type is SchemaTypes.Double. This double type is available thanks to a package called mongoose-double.
I don't know if MongoDB doesn't support Double so that's why we have this package, or is this because of MongoDB Version (it's on 3.6 AFAIK). But anyways, here's the code:
Schedule.aggregate([{
$match: findTerm
},
{
$facet: {
totalizer: [{
$group: {
_id: '$store',
totalServices: {
$sum: 1
},
totalValue: {
$sum: '$value'
},
totalComission: {
$sum: '$comissionValue'
}
}
}
],
data: [{
$project: {
'employee.name': 1,
'customer.name': 1,
'service.name': 1,
'info.channel': 1,
value: 1,
scheduleDate: 1,
scheduleStart: 1,
scheduleEnd: 1,
comissionValue: 1,
status: 1,
paymentMethod: 1
}
},
{
$sort: sort
},
{
$skip: req.body.limit * req.body.page
},
{
$limit: req.body.limit
}
]
}
}
]).exec((e, response) => {
if (e) {
// handle error
}
res.status(200).send(response[0]);
});
This findTerm is sent by the frontend app and has this format:
{ store: '5b16cceb56a44e2f6cd0324b',
status: { '$in': [ 0, 1, 2, 3 ] },
paymentMethod: { '$in': [ 0, 1, 2, 3, 4, 5 ] },
'info.channel': { '$in': [ 'app', 'admin' ] },
scheduleStart: { '$gte': '2019-11-01 00:00' },
scheduleEnd: { '$lte': '2020-03-31 23:59' }
}
My comissionValue field is in the root of my Schedule Schema:
comissionValue: {
type: SchemaTypes.Double,
default: 0
},
But my result is the following, as shown in my console.log in the frontend
As you can see my totalComission inside my totalizer is null, but my first object inside data has a comissionValue of 0.6.
How can i kno what's wrong here? I've tried different combinations of $facet, filtering only Schedules that has a comissionValue not equal 0 and null, but i only got a result of 0 for totalComission.
EDIT
Here's some sample data:
A Schedule object:
customer: {
id: "5e41a7ba11340930742aa689",
name: "renan lima",
phone: "+5511999999999",
email: "sampleemail#gmail.com",
doc: "00000000000",
avatar: null
},
employee: {
id: "5b16cebd29bcf613f02b6fb4",
name: "Anderson Zanardi",
avatar: "anderson.jpg"
},
service: {
noValue: false,
filters: [],
id: "5b637acd634e14086c9a3aea",
name: "Barba Masculina"
},
info: {
channel: "app",
id: "5e41a7ba11340930742aa689",
name: "renan lima"
},
comissionType: null,
comissionValue: 0,
paymentMethod: 0,
_id: "5e41a7c011340930742aa68a",
store: "5b16cceb56a44e2f6cd0324b",
scheduleDate: "2020-03-16T15:00:00.000Z",
scheduleStart: "2020-03-16 09:00",
scheduleEnd: "2020-03-16 09:30",
status: 2,
value: 30,
color: "blue",
logStatus: [],
__v: 0,
created: "2020-02-10T18:58:08.845Z",
updated: "2020-02-10T18:58:08.845Z"
My response received for the Schedule.aggregate:
{
"totalizer": [{
"_id": null,
"storesCount": [{
"store": "5b16cceb56a44e2f6cd0324b",
"count": 12
}],
"totalValue": 410.5,
"totalServices": 12,
"totalComission": 75
}],
"data": [{
"_id": "5e5d04dcb4a2f42204598ebf",
"service": {
"name": "Outros"
},
"info": {
"channel": "admin"
},
"comissionValue": 0,
"paymentMethod": 0,
"customer": {
"name": "teste"
},
"employee": {
"name": "Gabriel Barreto"
},
"scheduleDate": "2020-03-02T13:06:00.000Z",
"scheduleStart": "2020-03-02 10:06",
"scheduleEnd": "2020-03-02 10:36",
"status": 0,
"value": null
}]
}
Here the comission is 75, i don't know if it's because of the scheduleStart and scheduleDate in the findTerm on my $match that this time is starting at 2020-03-01 and ends at 2020-03-31 and in that range there's 3 schedules with 25 of comission.
Maybe my pagination is making it return null? Since i need it to sum all my comission for a given start/end range, even if in a certain page it doesn't have a comission.
EDIT 2
I added a sample data in Mongo Playground, the schedule array in the configuration column matchs the query used in the $match property on the query column.
Here's the link: https://mongoplayground.net/p/nmyAsY4g7LS
I am getting this output :
"Area":
[{
"AreaId": 2,
"AreaName":xyz,
"Data":
[{
"AssetId":somevalue,
"ActionId":somevalue,
}]
},
{
"AreaId": 2,
"AreaName":xyz,
"Data":
[{
"AssetId":somevalue,
"ActionId":somevalue,
}]
}]
But I want it merging to be like this :
"Area":[{
"AreaId": 2,
"AreaName":xyz,
"Data":
[{
"AssetId":somevalue,
"ActionId":somevalue,
},
{
"AssetId":someothervalue,
"ActionId":someothervalue,
}]
You could use groupBy of loadash. Code will look something like this
const {groupBy} = require("lodash");
const input = [
{
AreaId: 2,
AreaName: "Bedroom",
Data: [
{
Id: 7,
AssetId: 1,
Asset: "TubeLight",
ActionId: 1,
Action: "Clean",
TenantChargeBack: 0,
TenantChargeType: "%",
TenantChargeValue: 25,
Notes: "",
FilePath: "AWS_Bucket_Name/filename.jpg"
}
]
},
{
AreaId: 2,
AreaName: "Bedroom",
Data: [
{
Id: 8,
AssetId: 1,
Asset: "Bed",
ActionId: 3,
Action: "Repair",
TenantChargeBack: 1,
TenantChargeType: "%",
TenantChargeValue: 50,
Notes: "",
FilePath: "AWS_Bucket_Name/filename.jpg"
}
]
},
{
AreaId: 3,
AreaName: "Bathroom",
Data: [
{
Id: 9,
AssetId: null,
Asset: null,
ActionId: 2,
Action: "Replace",
TenantChargeBack: 1,
TenantChargeType: "$",
TenantChargeValue: 100,
Notes: "",
FilePath: "AWS_Bucket_Name/filename.jpg"
}
]
},
{
AreaId: 3,
AreaName: "Bathroom",
Data: [
{
Id: 10,
AssetId: 6,
Asset: "Jaar",
ActionId: 3,
Action: "Repair",
TenantChargeBack: 1,
TenantChargeType: "$",
TenantChargeValue: 100,
Notes: "",
FilePath: "AWS_Bucket_Name/filename.jpg"
}
]
},
{
AreaId: 2,
AreaName: "Bedroom",
Data: [
{
Id: 11,
AssetId: null,
Asset: null,
ActionId: 1,
Action: "Clean",
TenantChargeBack: 1,
TenantChargeType: "$",
TenantChargeValue: 50,
Notes: "",
FilePath: null
}
]
}
];
const groupedData = groupBy(input, i => i.AreaId);
const result = Object.keys(groupedData).map(j => {
const combined = groupedData[j];
return combined.reduce((a, b) => {
return {
"AreaId": a.AreaId,
"AreaName": a.AreaName,
"Data": a.Data.concat(b.Data)
};
})
});
console.log(JSON.stringify(result));
I have schema:
{
userName: String
postCount: Number,
commentCount: Number,
abuseCount: Number,
}
I need get sum all users counts all fields in result
example
{
"userName": "John"
"postCount": 5,
"commentCount": 1,
"abuseCount": 4,
}, {
"userName": "Bob"
"postCount": 11,
"commentCount": 41,
"abuseCount": 3,
}, {
"userName": "Alex"
"postCount": 2,
"commentCount": 15,
"abuseCount": 6,
}
result must be ~
{
"postCount": 18, (sum all postCount field users)
"commentCount": 57,
"abuseCount": 10,
}
How I can do this? Thx!
I was wondering what the best way to aggregate this data would be in Groovy?
Lets say I have the following data:
[
[id: 1, name: bob, age:20, numberOfPackages: 10, numberOfPurchases:20 ],
[id: 1, name: bob, age:20, numberOfPackages: 5, numberOfPurchases:6 ],
[id: 2, name: Rob, age:22, numberOfPackages: 3, numberOfPurchases:5 ],
]
and I want to transform it to the following (merge id/name/age but sum price/number of purchases per id):
[
[id: 1, name: bob, age:20, numberOfPackages: 15, numberOfPurchases:26 ],
[id: 2, name: Rob, age:22, numberOfPackages: 3, numberOfPurchases:5 ],
]
Summing the prices, and the number of purchases separately makes little sense, do you mean:
def data = [
[id: 1, name: 'bob', age:20, price: 10, numberOfPurchases:20],
[id: 1, name: 'bob', age:20, price: 5, numberOfPurchases:6],
[id: 2, name: 'rob', age:22, price: 3, numberOfPurchases:5]
]
data.groupBy { [id:it.id, name:it.name, age:it.age] }.collect { k, v ->
[id:k.id,
name:k.name,
age:k.age,
spend:v.collect { it.price * it.numberOfPurchases }.sum()]
}
Which gives:
[
[id:1, name:'bob', age:20, spend:230],
[id:2, name:'rob', age:22, spend:15]
]
It may be e.g.:
def data = [
[id: 1, name: 'bob', age:20, price: 10, numberOfPurchases:20 ],
[id: 1, name: 'bob', age:20, price: 5, numberOfPurchases:6 ],
[id: 2, name: 'rob', age:22, price: 3, numberOfPurchases:5 ],
]
data.groupBy { it.id }.collectEntries {
[
(it.key): [
name: it.value.name.first(),
age: it.value.first(),
price: it.value.sum { it.price },
numberOfPurchases: it.value.sum { it.numberOfPurchases },
]
]
}