Merging Area objects based on Similar Id - node.js

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));

Related

Mondogb $sum not working with SchemaTypes.Double

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

How can count the asscociation in sequelize js

When I make the following query to get the poll with option and each option have the voteCount. But it gives wring count.
router.get("/", (req, res) => {
Poll.findAll({
where: { subjectId: req.query.subjectId },
include: {
model: PollOption,
attributes: {
include: [[Sequelize.fn("COUNT", "pollVote.id"), "voteCount"]]
},
required: false,
include: {
model: PollVote,
// attributes: [],
required: false
}
},
group:['pollOptions.id']
}).then(poll => {
console.log(poll);
res.send({ poll });
});
});
I get this as the response
{
"poll": [
//Array of the poll
{
"id": 3,
"module_id": "mbbs",
"question": "Test Question Poll",
"pollOptions": [
{
"id": 1,
"pollId": 3,
"option": "Option 1",
"voteCount": 1,
"pollVotes": [
{
"id": 6,
"pollOptionId": 1,
"pollId": 3,
"userId": 3
}
]
},
{
"id": 2,
"pollId": 3,
"userId": 120,
"option": "Option 2",
"voteCount": 2,
//Vote must be 1 but return 2
"pollVotes": [
{
"id": 2,
"pollOptionId": 2,
"pollId": 3,
"userId": 1
}
]
}
]
},
{
"id": 4,
"module_id": "mbbs",
"question": "Test Question Poll 4",
"subjectId": 1,
"pollOptions": [
{
"id": 3,
"pollId": 4,
"option": "Option 1sd",
"voteCount": 1,
"pollVotes": []
}
]
}
]
}
Where voteCount is wrong.
How can I make it right.
Sql query is as follow
SELECT poll.id, poll.module_id, poll.question, poll.userId, poll.subjectId, poll.date, poll.expireDate, pollOptions.id AS pollOptions.id, pollOptions.pollId AS pollOptions.pollId, pollOptions.userId AS pollOptions.userId, pollOptions.option AS pollOptions.option, COUNT('pollVote.id') AS pollOptions.voteCount, pollOptions->pollVotes.id AS pollOptions.pollVotes.id, pollOptions->pollVotes.pollOptionId AS pollOptions.pollVotes.pollOptionId, pollOptions->pollVotes.pollId AS pollOptions.pollVotes.pollId, pollOptions->pollVotes.userId AS pollOptions.pollVotes.userId FROM poll AS poll LEFT OUTER JOIN pollOption AS pollOptions ON poll.id = pollOptions.pollId LEFT OUTER JOIN pollVote AS pollOptions->pollVotes ON pollOptions.id = pollOptions->pollVotes.pollOptionId WHERE poll.subjectId = '1' GROUP BY poll.id;
Your sequelize statement should be as follows -
router.get("/", (req, res) => {
Poll.findAll({
where: { subjectId: req.query.subjectId },
include: {
model: PollOption,
attributes: {
include: [[Sequelize.fn("COUNT", `pollOptions->pollVotes.id`), "voteCount"]]
},
required: false,
include: {
model: PollVote,
// attributes: [],
required: false
}
},
group:['pollOptions.id']
}).then(poll => {
console.log(poll);
res.send({ poll });
});
});
Hope it helps!

ArangoDB group and sort

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
}
]
}
]

MongoDB sort used more than the maximum RAM, but is using an index?

I'm debugging a site search feature with paginated results that is failing after an arbitrary number of pages.
search: Executor error during find command: OperationFailed: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit.
However, I'm confident that it is using an index:
winningPlan:
{ stage: 'PROJECTION',
transformBy:
{ score: { '$meta': 'textScore' },
shootId: 1,
title: 1,
publishDate: 1,
'media.images.indexImage': 1,
'media.images.adImage': 1,
'media.images.galleryImages': 1,
'media.images.portrait': 1,
'media.promos.images.410': 1,
'media.full.full.length': 1,
contentProducer: 1,
performers: 1,
site: 1 },
inputStage:
{ stage: 'TEXT',
indexPrefix: {},
indexName: 'textSearchIndex',
parsedTextQuery:
{ terms: [ 'milk' ],
negatedTerms: [],
phrases: [],
negatedPhrases: [] },
textIndexVersion: 3,
inputStage:
{ stage: 'TEXT_MATCH',
inputStage:
{ stage: 'TEXT_OR',
filter:
{ '$and':
[ { 'status.publishStatus': { '$eq': 'PUBLISHED' } },
{ publishDate: { '$lte': 2017-03-17T21:30:29.254Z } } ] },
inputStage:
{ stage: 'IXSCAN',
keyPattern:
{ _fts: 'text',
_ftsx: 1,
'status.publishStatus': 1,
publishDate: -1 },
indexName: 'textSearchIndex',
isMultiKey: true,
isUnique: false,
isSparse: false,
isPartial: false,
indexVersion: 2,
direction: 'backward',
indexBounds: {} } } } } },
rejectedPlans: [] },
The collection is ~1gb, 35k objects, average size 28.3 KiB.
The index, which is 22.8 MiB:
{
"description" : "text",
"performers.performerName" : "text",
"site.shortName" : "text",
"summary" : "text",
"title" : "text",
"status.publishStatus" : 1,
"publishDate" : -1
}
The query:
{
'status.publishStatus': 'PUBLISHED',
'publishDate': {
'$lte': new Date("Fri, 17 Mar 2017 21:30:29 GMT")
},
'$text': {
'$search': 'milk'
}
}
The sort:
{
score: {
$meta: 'textScore'
},
publishDate: -1
}
Practically, it's doing a find, sort, skip, limit, lean, select and finally exec.
Is it actually indexed? If it's not, what should I do differently?
If it is indexed, should I be increasing the internalQueryExecMaxBlockingSortBytes ?

Any way to group Mongodb query result by column?

Pretty new to Mongodb and I am trying to construct a query using Mongoose to get a desired result, if possible.
Test data:
{ id: 1, display_time: '01:00', name: 'test1' },
{ id: 2, display_time: '03:00', name: 'test2' },
{ id: 3, display_time: '01:00', name: 'test3' },
{ id: 4, display_time: '04:00', name: 'test4' },
{ id: 5, display_time: '01:00', name: 'test5' }
Desired result:
{
"01:00": [
{ id: 1, display_time: '01:00', name: 'test1' },
{ id: 3, display_time: '01:00', name: 'test3' },
{ id: 5, display_time: '01:00', name: 'test5' }
],
"03:00": [
{ id: 2, display_time: '03:00', name: 'test2' }
],
"04:00": [
{ id: 4, display_time: '04:00', name: 'test4' }
],
}
Basically it groups the documents based on the display_time field and returns it in that format. Is this possible with Mongo?
You can try somthing like this:
db.collection.aggregate(
[
{ $group : { _id : "$display_time", test: { $push: "$$ROOT" } } }
]
)
{
"_id" : "01:00",
"test" :
[
{ id: 1, display_time: '01:00', name: 'test1' },
{ id: 3, display_time: '01:00', name: 'test3' }
]
}
{
"_id" : "04:00",
"test" :
[
{ id: 4, display_time: '04:00', name: 'test4' }
]
}
For moar information http://docs.mongodb.org/manual/reference/operator/aggregation/group/

Resources