How to sum key value of all documents - javascript

I am just new to Mongo DB an facing problem in summation of the key value of all documents...
Here I am providing the sample data of Mongo DB-
{ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 }
{ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 }
{ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 }
{ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 }
{ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 }
All i want is to get the total value of key "amount", like for example-
50+100+25+125+25

You can query like this:
db.yourCollection.aggregate({ $group: { _id : null, sum : { $sum: "$amount" } } });
More details about aggregation can be found at here, and more details about sum can be found here

Related

How to merge one object id with same value into new array javascript [duplicate]

This question already has answers here:
Group objects by property in javascript
(8 answers)
Closed 2 months ago.
i have array of object transaction join with product and user table, i want to combine id with same value so it can display two different data in 1 object
Here's my data
let test = [
{
TransactionId: 1, //transaction table
username: "A", //user table
qty: 3, //product table
product_name: "Logitech G733",
price: $100,
description: "Lalalalala",
productId: 10
},
{
TransactionId: 2,
username: "B",
qty: 1,
product_name: "Razer",
price: $200,
description: "Blalalala",
productId: 12
},
{
TransactionId: 1,
username: "A",
qty: 1,
product_name: "Mousepad",
price: $50,
description: "This is mousepad",
productId: 7
},
{
TransactionId: 3,
username: "C",
qty: 2,
product_name: "Headphone",
price: $300,
description: "This is Headphone",
productId: 2
},
]
this is the output i want
let test = [
{
TransactionId: 1,
username: "A",
qty: [3, 1],
product_name: ["Logitech G733", "Mousepad"],
price: [$100, $50]
description: ["Lalalalala", "This is mousepad"],
productId: [10, 7]
},
{
TransactionId: 2,
username: "B",
qty: 1,
product_name: "Razer",
price: $200,
description: "Blalalala",
productId: 12
},
{
TransactionId: 3,
username: "C",
qty: 2,
product_name: "Headphone",
price: $300,
description: "This is Headphone",
productId: 2
},
]
i tried using reduce and Object.assign but the output only shows object with "Mousepad" not make array ["logitech G733","Mousepad"]
there should be many ways to do it, I used a map to combine the transactions and you can do whatever you need for the map after. For example
const test = [
{
TransactionId: 1, //transaction table
username: "A", //user table
qty: 3, //product table
product_name: "Logitech G733",
price: 100,
description: "Lalalalala",
productId: 10
},
{
TransactionId: 2,
username: "B",
qty: 1,
product_name: "Razer",
price: 200,
description: "Blalalala",
productId: 12
},
{
TransactionId: 1,
username: "A",
qty: 1,
product_name: "Mousepad",
price: 50,
description: "This is mousepad",
productId: 7
},
{
TransactionId: 3,
username: "C",
qty: 2,
product_name: "Headphone",
price: 300,
description: "This is Headphone",
productId: 2
},
]
const tMap = new Map();
test.forEach(transation => {
tMap.set(transation.TransactionId, { ...tMap.get(transation.TransactionId), ...transation });
})
If you wan to deep combined you can use some tool like lodash deep merge
tMap.set(transation.TransactionId, _.merge(tMap.get(transation.TransactionId), transation))
Then you have a map based on your tranastion Id, and you can decide what to do next. If you wan the array back you can simple run
console.log(Array.from(tMap.values()));

How to sort an array of objects then map through it in JavaScript? [duplicate]

This question already has answers here:
Sorting an array of objects by property values
(35 answers)
Closed 1 year ago.
I have an array of objects of products, I'm trying to sort them on the price (Low to High) and (High to Low) and then map through the sorted array to display the product.
And I can sort it by the time to which in here referred to it by created means the time the product has been created And updated means the last time the product got modified.
the JSX in the map because I'm using reactjs.
const products = [
{name: "keyboard",
id: "1",
created: 1614,
updated: 1620,
price: {
raw: 1,
formatted: "1.00",
}
},
{name: "shoes",
id: "2",
created: 1655,
updated: 1660,
price: {
raw: 2,
formatted: "2.00",
}
},
{name: "keyboard",
id: "1",
created: 1670,
updated: 1670,
price: {
raw: 1,
formatted: "1.00",
}
}
]
const sortedProducts = //products after been sorted
return(
sortedProducts.map(product =>
<div key={product.id}>
<h1>{product.name}</h1>
<h2>{product.price.formatted}</h2>
</div>
))
You can use sort() and compare the price property value
const products = [{
name: "keyboard",
id: "1",
created: 1614,
updated: 1620,
price: {
raw: 1,
formatted: "1.00",
}
},
{
name: "shoes",
id: "2",
created: 1655,
updated: 1660,
price: {
raw: 2,
formatted: "2.00",
}
},
{
name: "keyboard",
id: "1",
created: 1670,
updated: 1670,
price: {
raw: 1,
formatted: "1.00",
}
}
]
const sorted = products.sort((a, b) => a.price.formatted.localeCompare(b.price.formatted))
console.log(sorted);
Than you can map through the sorted array.
To make it "runnable" I changed the last part back from JSX into JavaScript
const products = [
{name: "screen",
id: "1",
created: 1614,
updated: 1620,
price: {
raw: 1.5,
formatted: "1.50",
}
},
{name: "shoes",
id: "2",
created: 1655,
updated: 1660,
price: {
raw: 2,
formatted: "2.00",
}
},
{name: "keyboard",
id: "1",
created: 1670,
updated: 1670,
price: {
raw: 1,
formatted: "1.00",
}
}
]
const sortedProducts = products.sort((a,b)=>a.created-b.created);
document.getElementById('here').innerHTML=sortedProducts.map(product =>
`<div key=${product.id}>
<h1>${product.name}</h1>
<h2>${product.price.formatted}</h2>
</div>`
).join("\n")
<div id="here"></div>
Instead of created you can fill in updated or price.raw for the other sort criteria.

How can I filter embedded documents within a document?

I was doing an integrated assignment consisting a lot of database operations and I was going okay until I had trouble filtering embedded documents within a documents.
My document looks like
{
flightId: "IND-101",
AircraftName: "Delta Airlines",
fare: 600,
availableSeats: 5,
status: "Running",
bookings: [
{
customerId: "P1001",
bookingId: 2001,
noOfTickets: 3,
bookingCost: 1800
},
{
customerId: "S1001",
bookingId: 2003,
noOfTickets: 2,
bookingCost: 1200
}
]
},
{
flightId: "IND-102",
AircraftName: "JetBlue",
fare: 750,
availableSeats: 20,
status: "Cancelled",
bookings: [
{
customerId: "P1001",
bookingId: 2002,
noOfTickets: 3,
bookingCost: 2250
},
{
customerId: "G1001",
bookingId: 2004,
noOfTickets: 2,
bookingCost: 1500
}
]
}
I have tried the below code but obviously, it is returning all the booking documents.
return flightModel.find({ $and: [{ flightId: flightId }, { "bookings.customerId": customerId }] }, { bookings:1, _id: 0 })
The variables flightId and customerId are given using a function.
If I give flightId as IND-101 and customerID as P1001, then the desired output is
{
customerId: "P1001",
bookingId: 2001,
noOfTickets: 3,
bookingCost: 1800
}
So how can I do this? How can I select a particular embedded document based on a filtering condition?
You can run an aggregate query to $filter and $project the fields you need.
Something like this should work.
let pipeline = [
{$match: {flightId: flightId}},
{$filter: {
input: '$bookings'
as: 'booking',
cond: {$eq: {'$$booking.customerId', customerId}}
}},
{$project: {
bookings: "$bookings"
}}
]
flightModel.aggregate(pipeline);

Mongodb aggregate push with index value of array

I am stucked in one aggregate query, Following is my data
Let database = [
{
_id: 'fefesf', name: 'John', info: {date: ISODate(), marks: '12'}
},
{
_id: 'uiuioo', name: 'John', info: {date: ISODate(), marks: '15'}
},
{
_id: 'erygbo', name: 'Ben', info: {date: ISODate(), marks: '18'}
}]
and my aggregate query is
var query = [{
$group: {
_id: '$name',
Marks: {
$push: {
x: '$index', ..............(not working right now)
y: '$info.marks'
}
}
}
}]
Is it possible to get index of grouped document as 'x' while pushing it in 'Marks' array. Like Output should be
[
{_id: 'John', Marks: [{x: 1, y: 12}, {x: 2, y: 15}]},
{_id: 'Ben',{x: 1, y: 18}}
]
Thanks in advance.!
Since mongoDB version 3.6 you can use $reduce for that*:
db.collection.aggregate([
{
$group: {
_id: "$name",
Marks: {$push: {y: "$info.marks"}}
}
},
{$project: {
Marks: {
$reduce: {
input: "$Marks",
initialValue: [],
in: {$concatArrays: [
"$$value",
[
{
y: "$$this.y",
x: {$add: [{$size: "$$value"}, 1]}
}
]
]
}
}
}
}
}
])
See how it works on the playground example
*Inspired by this answer

Meteorhacks:aggregate gives "MongoError: A pipeline stage specification object must contain exactly one field."

I'm trying to aggregate some simple data and getting the total time of each person in my case. I have added the package meteorhacks:aggregate to meteor, as some guide suggested. However I can't get it to work.
This is how the documents look in the mongoDB:
{startnumber: 1, name: "John Doe", time: 10000}
{startnumber: 1, name: "John Doe", time: 5000}
{startnumber: 2, name: "Jane Doe", time: 11000}
and this is how my aggregation looks in server/main.js:
Meteor.methods({
getTotalTime() {
rankings.aggregate({
$match: { startnumber: 1 },
$group: { _id: '$name', total: { $sum: '$time' } }
});
}
});
The desired result should hopefully be:
{startnumber: 1, name: "John Doe", time: 15000}
What am I doing wrong?
Each pipeline stage should be enclosed in its own document. Add a $project stage to format the response
.aggregate(
{ $match: { startnumber: 1 } },
{ $group: { _id: '$name', startnumber:{ $first:'$startnumber' }, total: { $sum: '$time' } } },
{ $project: { name: '$_id', startnumber:1, total:1, _id:0 } }
)

Categories