I have multiple documents In MobgoDB How to do to the group on "abc" and "xyz" and get one document. Please see the "Output Document".
need to do the union with ( Document 1 U Document 2 ) and (Document 1 U Document 3) .
U= Union
Document 1
{
"data": {
"Inside_data": {
"project": {
"abc": {
"alpha": 4,
"beta" : 45
},
"xyz": {
"alpha": 214,
"beta" : 431
}
}
}
}
}
Document 2
"Deal": {
"name": "abc",
"url" : "www.abc.com,
"email": [ "abc#gmail.com"],
"total": 2
}
Document 3
"Deal": {
"name": "xyz",
"url" : "www.googl.com,
"email": [ "xyz#gmail.com"],
"total": 25
}
Expected Output.
{
{
"name": "abc",
"url" : "www.abc.com,
"email": "abc#gmail.com",
"total": 2,
"alpha": 4,
"beta" : 45
},
{
"name": "xyz",
"url" : "www.googl.com,
"email": "xyz#gmail.com",
"total": 25,
"alpha": 214,
"beta" : 431
}
}
db.collection.aggregate([
{
$match: {
Deal: {
$exists: true
}
}
},
{
$lookup: {
from: "collection",
let: {
name: "$Deal.name"
},
pipeline: [
{
$match: {
data: {
$exists: true
}
}
},
{
$project: {
data: {
$reduce: {
input: {
$objectToArray: "$data.Inside_data.project"
},
initialValue: {},
in: {
$cond: [
{
$eq: [
"$$this.k",
"$$name"
]
},
"$$this.v",
"$$value"
]
}
}
}
}
},
{
$project: {
_id: 0,
alpha: "$data.alpha",
beta: "$data.beta"
}
}
],
as: "Deal.data"
}
},
{
$unwind: "$Deal.data"
}
])
Answer by #turivishal
Related
Considering an array like the one below which i'm trying to group by date and sum the durations:
[
{
"allDates": [
{
"duration": 153,
"date": "2021-10"
},
{
"duration": 20,
"date": "2021-11"
},
{
"duration": 181,
"date": "2021-11"
},
{
"duration": 180,
"date": "2021-11"
}
]
}
]
I'm trying to achieve a sum of the duration but grouped by the dates.
This is what i've tried so far:
db.collection.aggregate([
{
$addFields: {
durations: {
$arrayToObject: {
$map: {
input: "$allDates",
as: "allDate",
in: {
k: {
$toString: "$$allDate.date"
},
v: {
$sum: {
$map: {
input: "$allDates",
as: "kv",
in: {
$cond: {
if: {
$eq: [
{
$toString: "$allDate.date"
},
{
$toString: "$$kv.k"
}
]
},
then: "$$kv.duration",
else: 0
}
}
}
}
}
}
}
}
},
}
}
])
Unfortunately the result i get is:
[
{
"allDates": [
{
"date": "2021-10",
"duration": 153
},
{
"date": "2021-11",
"duration": 20
},
{
"date": "2021-11",
"duration": 181
},
{
"date": "2021-11",
"duration": 180
}
],
"durations": {
"2021-10": 534,
"2021-11": 534
}
}
]
So it's adding them all up for every key instead of for each one separately, what am i missing here?
Basically I'm expecting to get:
...
"durations": {
"2021-10": 153,
"2021-11": 381
}
Try this one:
db.collection.aggregate([
{
$unwind: "$allDates"
},
{
$group: {
_id: "$allDates.date",
duration: {
$sum: "$allDates.duration"
}
}
},
{
$group: {
_id: null,
durations: {
$push: {
k: "$_id",
v: "$duration"
}
}
}
},
{
$project: {
_id: 0,
durations: {
$arrayToObject: "$durations"
}
}
}
])
Mongo Playground
Explanation: How I can add the index of the array. please check the expected output, I have that array 10000+ elemets
[
{
"data": [
[
1000
],
[
20
],
[
300
],
[
40
]
]
}
]
The expected output will be with the index number.
{
"data": [{
"value": 1000,
"Index": 1
},
{
"value": 20,
"Index": 2
},
{
"value": 300,
"Index": 3
},
{
"value": 40,
"Index": 4
}
]
}
Would be this one:
db.collection.aggregate([
{
$set: {
data: {
$map: {
input: { $range: [0, { $size: "$data" }] },
as: "idx",
in: {
index: { $add: ["$$idx", 1] },
value: { $first: { $arrayElemAt: ["$data", "$$idx"] } }
}
}
}
}
}
])
Mongo Playground
Explanation :
A , B , C object have values. I have to match only those values with dic.data objects name. if its not match the then get the exception "No error found". see the Expected_output.
A B C get the relvant information.
I am using lookup to get dic data.
Note this should be handle dynamically. A B C values may differ, that impact on Expected_output
{
"_id": {
"A": "31",
"B": "40",
"C": "7"
},
"dic": [
{
"_id": "5487",
"data": {
"A": {
"31": {
"name": "NoFile"
},
"32": {
"name": " -- "
}
},
"B": {
"40": {
"label": "Label",
"description": "Error1"
},
"41": {
"label": " Data collection ",
"description": "error"
}
},
"C": {
"4": {
"description": "High problem"
},
"7": {
"description": " Normal"
}
}
}
}
]
}
"Expected_output": {
"A": {
"name" :"NoFile",
"code" : "31"
},
"B":{
"label" : "Label",
"description" : "Error1",
"code" : "40"
},
"C": {
"description" : "Normal",
"code" : "7"
}
}
$arrayElemAt to get first element from dic array
$objectToArray convert A object to array
$reduce to iterate loop of element above converted array and check condition if _id.A matches with data A then return specific field,
do the same process for B and C
db.collection.aggregate([
{
$addFields: {
dic: { $arrayElemAt: ["$dic", 0] }
}
},
{
$project: {
_id: 1,
dic: {
A: {
$reduce: {
input: { $objectToArray: "$dic.data.A" },
initialValue: "Not Found",
in: {
$cond: [
{ $eq: ["$$this.k", "$_id.A"] },
"$$this.v.name",
"$$value"
]
}
}
},
B: {
$reduce: {
input: { $objectToArray: "$dic.data.B" },
initialValue: "Not Found",
in: {
$cond: [
{ $eq: ["$$this.k", "$_id.B"] },
"$$this.v.description",
"$$value"
]
}
}
},
C: {
$reduce: {
input: { $objectToArray: "$dic.data.C" },
initialValue: "Not Found",
in: {
$cond: [
{ $eq: ["$$this.k", "$_id.C"] },
"$$this.v.description",
"$$value"
]
}
}
}
}
}
}
])
Playground
{
"_id": "null",
"data": [
{
"name": "abc",
"id": "123"
},
{
"name": "xzy",
"id": "123"
}
]
}
Explanation: the name value will become an object name. also want to convert it into one single document, that contains all the objects. abc and xyz is dynamically coming as a parameter.
Expected Output.
{
"data": {
"abc": {
"name": "abc",
"id": "100"
},
"xyz": {
"name": "xzy",
"id": "123"
}
}
}
Try this:
db.testCollection.aggregate([
{
$project: {
"array": {
$map: {
input: "$data",
as: "item",
in: {
k: "$$item.name",
v: {
"name": "$$item.id",
"id": "$$item.name"
}
}
}
}
}
},
{ $unwind: "$array" },
{
$group: {
_id: "$null",
"data": { $push: "$array" }
}
},
{
$project: {
"data": { $arrayToObject: "$data" }
}
}
]);
I have a user document with the following structure:
{
"_id": {
"$oid": "5e636c552b872f00178033bf"
},
"finance": {
"expenditure": [
{
"status": true,
"_id": {
"$oid": "5e636d442b872f00178033d4"
},
"amount": {
"$numberInt": "900"
},
"category": "Coffee"
},
{
"status": true,
"_id": {
"$oid": "5e636d492b872f00178033d5"
},
"amount": {
"$numberInt": "1000"
},
"category": "Coffee"
},
{
"status": true,
"_id": {
"$oid": "5e636d532b872f00178033d6"
},
"amount": {
"$numberInt": "3000"
},
"category": "Sport"
},
{
"status": true,
"_id": {
"$oid": "5e636d572b872f00178033d7"
},
"amount": {
"$numberInt": "1000"
},
"category": "Sport"
},
],
"customcategories": [
{
"budget": {
"$numberInt": "200"
},
"_id": {
"$oid": "5e636c552b872f00178033c7"
},
"title": "Sport"
},
{
"budget": {
"$numberInt": "100"
},
"_id": {
"$oid": "5e636c552b872f00178033c8"
},
"title": "Coffee"
}
]
}
}
My previos command is this one (you don't have to mind the status and the currentdate) :
User.aggregate([
{
$match: {
_id: req.user._id
}
},
{
$unwind: "$finance.expenditure"
},
{
$match: {
"finance.expenditure.status": true
}
},
{
$sort: {
"finance.expenditure.currentdate": -1
}
},
{
$group: {
_id: "$finance.expenditure.category",
amount: {
$sum: "$finance.expenditure.amount",
}
}
},
{
$project: {
_id: 0,
category: "$_id",
amount: 1
}
}
])
The Result looks like this :
{
"expenditure": [
{
"amount": 1900,
"category": "Coffee"
},
{
"amount": 4000,
"category": "Sport"
}
]
}
I would like to add the my grouped elements the budget from the associated "customcategory".
So that it looks like this :
{
"expenditure": [
{
"amount": 1900,
"category": "Coffee",
"budget" : 100
},
{
"amount": 4000,
"category": "Sport",
"budget" : 200
}
]
}
I tried several things but nothing works of the $lookup method worked for me.
I hope some can help me :)
give this pipeline a try:
db.collection.aggregate([
{
$match: { _id: ObjectId("5e636c552b872f00178033bf") }
},
{
$unwind: "$finance.expenditure"
},
{
$match: { "finance.expenditure.status": true }
},
{
$sort: { "finance.expenditure.currentdate": -1 }
},
{
$group: {
_id: "$finance.expenditure.category",
amount: { $sum: "$finance.expenditure.amount"},
categories: { $first: '$finance.customcategories' }
}
},
{
$project: {
_id: 0,
category: "$_id",
amount: 1,
budget: {
$arrayElemAt: [
{
$map: {
input: {
$filter: {
input: '$categories',
cond: { $eq: ['$$this.title', '$_id'] }
}
},
in: '$$this.budget'
}
},
0
]
}
}
}
])
https://mongoplayground.net/p/adsWInz3wgY
Try this one:
User.aggregate([
{
$match: {
_id: mongoose.Types.ObjectId(req.user._id)
}
},
{
$sort: {
"finance.expenditure.currentdate": -1
}
},
{
$unwind: "$finance.expenditure"
},
{
$unwind: "$finance.customcategories"
},
{
$match: {
"finance.expenditure.status": true
}
},
{
$group: {
_id: "$finance.expenditure.category",
amount: {
$addToSet: "$finance.expenditure"
},
customcategories: {
$addToSet: "$finance.customcategories"
}
}
},
{
$project: {
_id: 0,
"amount": {
$sum: "$amount.amount"
},
"category": "$_id",
"budget": {
$sum: {
$let: {
vars: {
budget: {
$filter: {
input: "$customcategories",
cond: {
$eq: [
"$_id",
"$$this.title"
]
}
}
}
},
in: "$$budget.budget"
}
}
}
}
}
])
//.exec(function(err, result){})
MongoPlayground