MongoDB doesn't group properly - mongodb

I am using mongoDB with .NET and for over a year, the same query worked properly.
For a single date range - 04.06.22. - 05.06.22. query malfunctioned and didn't group only one product by ID, so I am getting 2 products with the same ID.
Query (will delete unnecessary params, to make it easier to understand):
.FilterByCustomer(filter.CustomerId)
.FilterByTerminals(filter.Terminals)
.FilterByDateRange("FromLocalDateTime", "ToLocalDateTime", filter.LocalDateRange)
.Unwind("SalesForSingleProductReports", false)
.Unwind("SalesForSingleProductReports.RevenueAndSalesPerCurrency", false)
.Group(
#" _id : {
ProductInfo: '$SalesForSingleProductReports.ProductInfo',
CurrencyInfo: '$SalesForSingleProductReports.RevenueAndSalesPerCurrency.CurrencyInfo'
},
RevenueAndSalesPerCurrency: {
$push: {
Revenue: {$sum: '$SalesForSingleProductReports.RevenueAndSalesPerCurrency.Revenue'},
}
}
}")
.Group(#"_id : '$_id.ProductInfo',
RevenueAndSalesPerCurrency: {$push: {
CurrencyInfo: '$_id.CurrencyInfo',
Revenue: {$sum: '$RevenueAndSalesPerCurrency.Revenue'},
}")
.Project(#"_id:0,
ProductInfo:'$_id',
'RevenueAndSalesPerCurrency': 1")
.Compile();
The result that I am getting is multiple products, but one is duplicated and has different revenue values, but same ID:
[{
"productInfo": {
"productId": "id-111",
"productName": null,
"productInternalCode": "internal-111",
"productCategoryId": "prod-cat-111",
"productCode": null,
"brand": null,
"countryCode": null
},
"revenueAndSalesPerCurrency": [
{
"currencyInfo": {
"currencyId": "curr-Id",
"code": "EUR",
"symbol": "€"
},
"revenue": 1680,
}
]
},
{
"productInfo": {
"productId": "id-111",
"productName": null,
"productInternalCode": "internal-111",
"productCategoryId": "prod-cat-111",
"productCode": null,
"brand": null,
"countryCode": null
},
"revenueAndSalesPerCurrency": [
{
"currencyInfo": {
"currencyId": "curr-id",
"code": "EUR",
"symbol": "€"
},
"revenue": 3080,
}
]
}
]
Here's one record from the collection on which actions are done:
"_id" : ObjectId("id-string"),
"CreatedAt" : ISODate("2021-11-10T10:14:10.116Z"),
"UpdatedAt" : ISODate("2021-11-10T10:14:10.116Z"),
"CreatedByUserId" : null,
"UpdatedByUserId" : null,
"Version" : null,
"IsDeleted" : false,
"ReportType" : "AggregatedSingleProductSalesReportForTerminalAndDate",
"ReportId" : "report-id,
"CustomerId" : "cust-id",
"FromUtcDateTime" : ISODate("2021-11-01T23:00:00.000Z"),
"ToUtcDateTime" : ISODate("2021-11-02T22:59:59.999Z"),
"FromLocalDateTime" : ISODate("2021-11-02T00:00:00.000Z"),
"ToLocalDateTime" : ISODate("2021-11-02T23:59:59.999Z"),
"TransactionIds" : [
"trans-id-1",
"trans-id-2",
],
"TerminalId" : "terminal-id",
"LocalDate" : "2021-11-02",
"SalesForSingleProductReports" : [
{
"ProductInfo" : {
"ProductId" : "prod-id",
"ProductName" : null,
"ProductInternalCode" : "internal-string",
"ProductCategoryId" : "prod-category-id"
},
"RevenueAndSalesPerCurrency" : [
{
"CurrencyInfo" : {
"CurrencyId" : "euro-curr",
"Code" : "GBP",
"Symbol" : "£"
},
"Revenue" : 180,
}
]
},
{
"ProductInfo" : {
"ProductId" : "prod-id-2",
"ProductName" : null,
"ProductInternalCode" : "internal-string-2",
"ProductCategoryId" : "prod-category-id-2"
},
"RevenueAndSalesPerCurrency" : [
{
"CurrencyInfo" : {
"CurrencyId" : "euro-curr",
"Code" : "GBP",
"Symbol" : "£"
},
"Revenue" : 90,
}
]
}
]
}```

Related

MongoDB Shell aggregate pipeline not grouping how I want it to

Design and implement a MongoDB aggregation pipeline to show the total number of employees by state for all companies that have offices in the United States.
My original solution is this:
db.research.aggregate([
{ $match: { "offices.country_code": "USA" } },
{ $group: { _id: "$offices.state_code", total: { $sum: "$number_of_employees" } } }
])
The problem is that each document can have multiple offices, resulting in many of the returned results being combinations of different state codes. For example, these are some results:
{ "_id" : [ null, "IL" ], "total" : 61 }
{ "_id" : [ "NY", "CA", null ], "total" : 20 }
{ "_id" : [ "UT", "CA", "NY", null ], "total" : 0 }
{ "_id" : [ null, "GA", null, null ], "total" : 0 }
{ "_id" : [ "WA", "WA", "NY", "CA", "MA", null ], "total" : 1650 }
{ "_id" : [ "TX", "IL" ], "total" : 22 }
{ "_id" : [ "MA", "NV" ], "total" : 0 }
{ "_id" : [ "NY", "CO", "CA" ], "total" : 0 }
{ "_id" : [ "MA", "MA" ], "total" : 25 }
{ "_id" : [ "VA", "NY", "CA", null, null ], "total" : 5 }
{ "_id" : [ "CA", "CA", "NY", "IL", "CA", null, null ], "total" : 0 }
{ "_id" : [ "CA", null, "NY", "CA", null ], "total" : 50 }
{ "_id" : [ "CA", "ME" ], "total" : 2 }
{ "_id" : [ "MA" ], "total" : 255864 }
{ "_id" : [ "DE" ], "total" : 409 }
{ "_id" : [ "DC", "CA", "VA" ], "total" : 7000 }
{ "_id" : [ "ND" ], "total" : 18 }
{ "_id" : [ null, null, "VA", null, null, null, "VT", null, null ], "total" : 0 }
{ "_id" : [ "NC", null, null, null ], "total" : 290 }
{ "_id" : [ "SC", "NY" ], "total" : 0 }
Instead, I want each ``state_code` listed separately with the number of employees for that state. If a document has multiple state codes, it should count towards each of them. For example, If a document has 1000 employees and the state codes "NY" and "CA", the 1000 should count towards both of those sums. I don't want it to list unique combinations of state codes like it currently is. Any ideas?
Deconstruct offices array before group,
$unwind to deconstruct offices array
db.research.aggregate([
{ $match: { "offices.country_code": "USA" } },
{ $unwind: "$offices" },
{
$group: {
_id: "$offices.state_code",
total: { $sum: "$number_of_employees" }
}
}
])
Playground

Group and Merge array of objects

I am struggling around with the aggregation pipeline feature from MongoDB.
So far the output for one result looks like this:
{
"type": "inbound",
"sender": "postAG",
"receiver": "maxMusterMan",
"datetime": "20191125",
"info": [
{
"q": "A",
"value": "5",
"name": null,
"plz": 1234
},
{
"q": "B",
"value": "AS",
"name": "ABS",
"plz": null
},
{
"q": "A",
"value": "5",
"name": "aa",
"plz": null
},
... more objects
]
}
The final result should look like:
{
"type": "inbound",
"sender": "postAG",
"receiver": "maxMusterMan",
"datetime": "20191125",
"info": [
{
"q": "A",
"value": "0",
"name": "aa",
"plz": 1234
},
{
"q": "B",
"value": "AS",
"name": "ABS"
}
]
}
So in a nutshell, I want to group the values from the array field info by the "q" field and merge the objects (newer one overwrites the old value).
Further I would like to remove all the values with value "" or null;
There are more fields in the real payload, so I would like to avoid to add a $cond for each field of the object.
Some approaches so far from my side:
for the cleanup, use a UDF, but this is not possible in the pipeline.
use map-reduce for the group and merge, not available in the pipeline.
Please consider that the input file is the output from the several pipeline steps.
So I can not just use map-reduce alone, first I need the pipeline too.
My idea was to create two views, first will do the pipeline stuff and second map-reduce, is this a good solution?
Thx
Andreas
I didn't really understand from your explanation if you can or cannot use map-reduce.
However assuming you can't and you have to 'concat' the pipelines there is no 'generic' workaround for multiple fields - you have to create a condition for each in the pipeline.
With that said here is a working pipeline:
db.collection.aggregate(
[
{
"$unwind" : "$info"
},
{
"$group" : {
"_id" : "$info.q",
"type" : {
"$first" : "$type"
},
"sender" : {
"$first" : "$sender"
},
"receiver" : {
"$first" : "$receiver"
},
"datetime" : {
"$first" : "$datetime"
},
"values" : {
"$push" : "$info.value"
},
"names" : {
"$push" : "$info.name"
},
"plz" : {
"$push" : "$info.plz"
}
}
},
{
"$project" : {
"_id" : 1.0,
"type" : 1.0,
"sender" : 1.0,
"receiver" : 1.0,
"datetime" : 1.0,
"values" : {
"$filter" : {
"input" : "$values",
"as" : "curr",
"cond" : {
"$or" : [
{
"$ne" : [
"$$curr",
null
]
},
{
"$ne" : [
"$$curr",
""
]
}
]
}
}
},
"names" : {
"$filter" : {
"input" : "$names",
"as" : "curr",
"cond" : {
"$or" : [
{
"$ne" : [
"$$curr",
null
]
},
{
"$ne" : [
"$$curr",
""
]
}
]
}
}
},
"plz" : {
"$filter" : {
"input" : "$plz",
"as" : "curr",
"cond" : {
"$or" : [
{
"$ne" : [
"$$curr",
null
]
},
{
"$ne" : [
"$$curr",
""
]
}
]
}
}
}
}
},
{
"$project" : {
"sender" : 1.0,
"receiver" : 1.0,
"datetime" : 1.0,
"type" : 1.0,
"_id" : 1.0,
"value" : {
"$cond" : {
"if" : {
"$gt" : [
{
"$size" : "$values"
},
0.0
]
},
"then" : {
"$arrayElemAt" : [
"$values",
-1.0
]
},
"else" : null
}
},
"name" : {
"$cond" : {
"if" : {
"$gt" : [
{
"$size" : "$names"
},
0.0
]
},
"then" : {
"$arrayElemAt" : [
"$names",
-1.0
]
},
"else" : null
}
},
"plz" : {
"$cond" : {
"if" : {
"$gt" : [
{
"$size" : "$plz"
},
0.0
]
},
"then" : {
"$arrayElemAt" : [
"$plz",
-1.0
]
},
"else" : null
}
}
}
},
{
"$addFields" : {
"infoArray" : [
{
"k" : "type",
"v" : "$_id"
},
{
"k" : "value",
"v" : "$value"
},
{
"k" : "name",
"v" : "$name"
},
{
"k" : "plz",
"v" : "$plz"
}
]
}
},
{
"$addFields" : {
"info" : {
"$arrayToObject" : {
"$filter" : {
"input" : "$infoArray",
"as" : "curr",
"cond" : {
"$ne" : [
"$$curr.v",
null
]
}
}
}
}
}
},
{
"$group" : {
"_id" : null,
"type" : {
"$first" : "$type"
},
"sender" : {
"$first" : "$sender"
},
"receiver" : {
"$first" : "$receiver"
},
"datetime" : {
"$first" : "$datetime"
},
"info" : {
"$push" : "$info"
}
}
}
]
)

MongoDB Use $group for the subset after $group

I just learned mongoDB, I am trying to find some repeat customer info through my customer database.
The sample collection:
{
"_id" : ObjectId("5b7617e48146d8bae"),
"amazon_id" : "112",
"date" : "2018-01-25T18:40:55-08:00",
"email" : "xxxxx#marketplace.amazon.com",
"buy_name" : "xxxxx",
"sku" : "NPC-50",
"qty" : 8,
"price" : 215.92,
"reci_name" : "XXXXX",
"street1" : "XXXXX",
"street2" : "",
"street3" : "",
"city" : "XXXXX",
"state" : "XXXXX",
"zip_code" : "XXXXXX"
}
{
"_id" : ObjectId("5b761712e48146d8bae"),
"amazon_id" : "114",
"date" : "2018-01-27T18:40:55-08:00",
"email" : "xxxxx#marketplace.amazon.com",
"buy_name" : "xxxxx",
"sku" : "ABC",
"qty" : 1,
"price" : 19.99,
"reci_name" : "XXXXX",
"street1" : "XXXXX",
"street2" : "",
"street3" : "",
"city" : "XXXXX",
"state" : "XXXXX",
"zip_code" : "XXXXXX"
}
I group all customer info by their email id, and here is my code:
db.getCollection('order').aggregate([
{ $group: { _id: "$email",
OrderInfo: {$push: {orderId: "$amazon_id", sku: "$sku", qty: "$qty", price:"$price"
}},
CustomerInfo: {$addToSet: {buyName: "$buy_name",reName: "$reci_name", email: "$email", street1: "$street1",
street2: "$street2", city: "$city", state: "$state", zipCode: "$zip_code"} }
}},
{ $project: {_id: 1, OrderInfo: 1, CustomerInfo:1, total_price:{$sum: "$OrderInfo.price"} }},
{ $match: {total_price: {$gt:100} } },
{ $sort: {total_price:-1}},
], { allowDiskUse: true } );
It shows me the result:
{
"_id" : "xxxxxxx#marketplace.amazon.com",
"OrderInfo" : [
{
"orderId" : "112",
"sku" : "NPC-50",
"qty" : 8,
"price" : 215.92
},
{
"orderId" : "112",
"sku" : "NPC-50",
"qty" : 1,
"price" : 26.99
},
{
"orderId" : "114",
"sku" : "NPC-50",
"qty" : 1,
"price" : 26.99
},
{
"orderId" : "114",
"sku" : "ABC",
"qty" : 1,
"price" : 19.99
},
{
"orderId" : "116",
"sku" : "ABC",
"qty" : 1,
"price" : 19.99
},
],
"CustomerInfo" : [
{
"buyName" : "xxxxxxxxx",
"reName" : "xxxxxxxxxxxx",
"email" : "xxxxxxxxxxxx#marketplace.amazon.com",
"street1" : "xxxxxxxxxxx",
"street2" : "",
"city" : "xxxxxxxxxx",
"state" : "xxxxxxxxxxxx",
"zipCode" : "xxxxxxxxxx"
},
{
"buyName" : "xxxxxxxxxx",
"reName" : "xxxxxx",
"email" : "xxxxxxxx#marketplace.amazon.com",
"street1" : "xxxxxxxxxxx",
"street2" : "",
"city" : "xxxxx",
"state" : "xxxx",
"zipCode" : "xxxxxxxx"
}
],
"total_price" : 309.88
}
However, I want to group the sku and sum up the qty and price in the OrderInfo Set. My expected output is something like:
{
"OrderInfo" : [
{
"sku": "NPC-50",
"qty": 10,
"price": 269.9
},
{
"sku": "ABC",
"qty": 2,
"price": 39.98
},
],
"CustomerInfo" : [
{
"buyName" : "xxxxxxxxx",
"reName" : "xxxxxxxxxxxx",
"email" : "xxxxxxxxxxxx#marketplace.amazon.com",
"street1" : "xxxxxxxxxxx",
"street2" : "",
"city" : "xxxxxxxxxx",
"state" : "xxxxxxxxxxxx",
"zipCode" : "xxxxxxxxxx"
},
{
"buyName" : "xxxxxxxxxx",
"reName" : "xxxxxx",
"email" : "xxxxxxxx#marketplace.amazon.com",
"street1" : "xxxxxxxxxxx",
"street2" : "",
"city" : "xxxxx",
"state" : "xxxx",
"zipCode" : "xxxxxxxx"
}
],
"total_price" : 309.88
}
Any Help will be appreciated.
You can use below aggregation.
db.order.aggregate([
{"$group":{
"_id":{"email":"$email","sku":"$sku"},
"qty":{"$sum":"$qty"},
"price":{"$sum":"$price"},
"CustomerInfo":{
"$addToSet":{
"buyName":"$buy_name",
"reName":"$reci_name",
"email":"$email",
"street1":"$street1",
"street2":"$street2",
"city":"$city",
"state":"$state",
"zipCode":"$zip_code"
}
}
}},
{"$group":{
"_id":"$_id.email",
"OrderInfo":{"$push":{"sku":"$_id.sku","qty":"$qty","price":"$price"}},
"total_price":{"$sum":"$price"},
"CustomerInfo":{"$first":"$CustomerInfo"}
}},
{"$match":{"total_price":{"$gt":100}}},
{"$sort":{"total_price":-1}}
])
You can try below aggregation
db.collection.aggregate([
{ "$group": {
"_id": {
"email": "$email",
"sku": "$sku"
},
"CustomerInfo": {
"$addToSet": {
"buyName": "$buy_name",
"otherFields": "$otherFields",
}
},
"price": { "$sum": "$price" },
"qty": { "$sum": "$qty" }
}},
{ "$group": {
"_id": "$_id.email",
"CustomerInfo": { "$first": "$CustomerInfo" },
"OrderInfo": {
"$push": {
"sku": "$_id.sku",
"qty": "$qty",
"price": "$price"
}
}
}}
])

get length of array via variable just created mongodb

I am new to mongodb, I have a dataset that looks like the following, and I'm trying to Write an aggregation query that will determine the number of unique companies with which an individual has been associated.
Schema:
{
"_id" : ObjectId("52cdef7c4bab8bd675297d8b"),
"name" : "AdventNet",
"permalink" : "abc3",
"crunchbase_url" : "http://www.crunchbase.com/company/adventnet",
"homepage_url" : "http://adventnet.com",
"blog_url" : "",
"blog_feed_url" : "",
"twitter_username" : "manageengine",
"category_code" : "enterprise",
"number_of_employees" : 600,
"founded_year" : 1996,
"deadpooled_year" : 2,
"tag_list" : "",
"alias_list" : "Zoho ManageEngine ",
"email_address" : "pr#adventnet.com",
"phone_number" : "925-924-9500",
"description" : "Server Management Software",
"created_at" : ISODate("2007-05-25T19:24:22Z"),
"updated_at" : "Wed Oct 31 18:26:09 UTC 2012",
"overview" : "<p>AdventNet is now Zoho ManageEngine.</p>\n\n<p>Founded in 1996, AdventNet has served a diverse range of enterprise IT, networking and telecom customers.</p>\n\n<p>AdventNet supplies server and network management software.</p>",
"image" : {
"available_sizes" : [
[
[
150,
55
],
"assets/images/resized/0001/9732/19732v1-max-150x150.png"
],
[
[
150,
55
],
"assets/images/resized/0001/9732/19732v1-max-250x250.png"
],
[
[
150,
55
],
"assets/images/resized/0001/9732/19732v1-max-450x450.png"
]
]
},
"products" : [ ],
"relationships" : [
{
"is_past" : true,
"title" : "CEO and Co-Founder",
"person" : {
"first_name" : "Sridhar",
"last_name" : "Vembu",
"permalink" : "sridhar-vembu"
}
},
{
"is_past" : true,
"title" : "VP of Business Dev",
"person" : {
"first_name" : "Neil",
"last_name" : "Butani",
"permalink" : "neil-butani"
}
},
{
"is_past" : true,
"title" : "Usabiliy Engineer",
"person" : {
"first_name" : "Bharath",
"last_name" : "Balasubramanian",
"permalink" : "bharath-balasibramanian"
}
},
{
"is_past" : true,
"title" : "Director of Engineering",
"person" : {
"first_name" : "Rajendran",
"last_name" : "Dandapani",
"permalink" : "rajendran-dandapani"
}
},
{
"is_past" : true,
"title" : "Market Analyst",
"person" : {
"first_name" : "Aravind",
"last_name" : "Natarajan",
"permalink" : "aravind-natarajan"
}
},
{
"is_past" : true,
"title" : "Director of Product Management",
"person" : {
"first_name" : "Hyther",
"last_name" : "Nizam",
"permalink" : "hyther-nizam"
}
},
{
"is_past" : true,
"title" : "Western Regional OEM Sales Manager",
"person" : {
"first_name" : "Ian",
"last_name" : "Wenig",
"permalink" : "ian-wenig"
}
}
],
"competitions" : [ ],
"providerships" : [
{
"title" : "DHFH",
"is_past" : true,
"provider" : {
"name" : "A Small Orange",
"permalink" : "a-small-orange"
}
}
],
"total_money_raised" : "$0",
"funding_rounds" : [ ],
"investments" : [ ],
"acquisition" : null,
"acquisitions" : [ ],
"offices" : [
{
"description" : "Headquarters",
"address1" : "4900 Hopyard Rd.",
"address2" : "Suite 310",
"zip_code" : "94588",
"city" : "Pleasanton",
"state_code" : "CA",
"country_code" : "USA",
"latitude" : 37.692934,
"longitude" : -121.904945
}
],
"milestones" : [ ],
"video_embeds" : [ ],
"screenshots" : [
{
"available_sizes" : [
[
[
150,
94
],
"assets/images/resized/0004/3400/43400v1-max-150x150.png"
],
[
[
250,
156
],
"assets/images/resized/0004/3400/43400v1-max-250x250.png"
],
[
[
450,
282
],
"assets/images/resized/0004/3400/43400v1-max-450x450.png"
]
],
"attribution" : null
}
],
"external_links" : [ ],
"partners" : [ ]
}
Here is the query I tried:
db.companies.aggregate([{
$match: {
"relationships.person": {
$ne: null
}
}
}, {
$project: {
relationships: 1,
_id: 0
}
}, {
$unwind: "$relationships"
}, {
$group: {
_id: "$relationships.person",
count: {
$addToSet: "$relationships"
}
}
}])
I think I now need to get the length of the $relationships array? How would I do that?
When you only want the size of the array you really don't need to unwind...
Just use $size.
Alter your aggregation to:
db.companies.aggregate([{
$match: {
"relationships.person": {
$ne: null
}
}
}, {
$project: {
relationships: 1,
_id: 0,
relationship_size : { $size : "$relationships"}
}
}
}])
This should give you the result you want
From the comment i understand you want some more logic in the aggregation, from outta my head i would alter your aggregation to:
db.companies.aggregate([{
$match: {
"relationships.person": {
$ne: null
}
}
}, {
$project: {
relationships: 1,
_id: 0
}
}, {
$unwind: "$relationships"
}, {
$group: {
_id: "$relationships.person.permalink",
count : {$sum : 1}
}
}])
I can't find a "company name" in your relationships array so i use the permalink property

group by date and then by currecny and sum mongo records

I have the following records on my mongo database
> db.orders.find({});
{
"_id" : "WEB3",
"currency" : "USD",
"company" : "b",
"user_id" : "b",
"timestamp" : ISODate("2015-06-26T12:13:18.570Z"),
"details" : {
"ordered" : {
"total" : 1910.4,
"deliveryVAT" : 120,
"delivery" : 600,
"goodsVAT" : 198.4,
"goodsTotal" : 992
}
}
}
{
"_id" : "WEB1",
"currency" : "GBP",
"company" : "a",
"user_id" : "a",
"timestamp" : ISODate("2015-06-26T12:11:08.570Z"),
"details" : {
"ordered" : {
"total" : 1910.4,
"deliveryVAT" : 120,
"delivery" : 600,
"goodsVAT" : 198.4,
"goodsTotal" : 992
}
}
}
{
"_id" : "WEB2",
"currency" : "GBP",
"company" : "a",
"user_id" : "a",
"timestamp" : ISODate("2015-06-26T12:11:18.570Z"),
"details" : {
"ordered" : {
"total" : 1910.4,
"deliveryVAT" : 120,
"delivery" : 600,
"goodsVAT" : 198.4,
"goodsTotal" : 992
}
}
}
here is the insert, statement:
db.orders.insert( { "_id" : "WEB1", "currency" : "GBP", "company" : "a", "user_id" : "a", "timestamp" : ISODate("2015-06-26T12:11:08.570Z"), "details" : { "ordered" : { "total" : 1910.4, "deliveryVAT" : 120, "delivery" : 600, "goodsVAT" : 198.4, "goodsTotal" : 992 } } });
db.orders.insert( { "_id" : "WEB2", "currency" : "GBP", "company" : "a", "user_id" : "a", "timestamp" : ISODate("2015-06-26T12:11:18.570Z"), "details" : { "ordered" : { "total" : 1910.4, "deliveryVAT" : 120, "delivery" : 600, "goodsVAT" : 198.4, "goodsTotal" : 992 } } });
db.orders.insert( { "_id" : "WEB3", "currency" : "USD", "company" : "b", "user_id" : "b", "timestamp" : ISODate("2015-06-26T12:13:18.570Z"), "details" : { "ordered" : { "total" : 1910.4, "deliveryVAT" : 120, "delivery" : 600, "goodsVAT" : 198.4, "goodsTotal" : 992 } } });
What is the correct way to group by date and then group by currency, so that I get a result similar to:
{ [ "date": "2015-06-26",
"currency": "USD",
"total": 1910.4,
"no_of_orders": 1],
[ "date": "2015-06-26",
"currency": "GBP",
"total": 3820.8,
"no_of_orders": 2]]
}
From a previous post mongodb sort result of aggregate query and display day name I am able to get the number of orders made for each day, but then I am unsure how to pipe the results and split those by currency and then total the result?
Any advice much appreciated
You could try the following aggregation pipeline which groups the documents by Year-Month-Day and the currency to get the desired results:
db.orders.aggregate([
{
"$group": {
"_id": {
"day": { "$dayOfMonth" : "$timestamp" },
"month": { "$month" : "$timestamp" },
"year": { "$year" : "$timestamp" },
"currency": "$currency"
},
"total": { "$sum": "$details.ordered.total" },
"no_of_orders": { "$sum": 1 }
}
},
{
"$project": {
"_id": 0,
"dateDay": {
"$concat": [
{"$substr" : [ "$_id.day", 0, 2]}, "-",
{"$substr" : [ "$_id.month", 0, 2]}, "-",
{"$substr" : [ "$_id.year", 0, 4]}
]
},
"total": 1,
"no_of_orders": 1,
"currency": "$_id.currency"
}
}
])
Sample Output
/* 0 */
{
"result" : [
{
"total" : 1910.4,
"no_of_orders" : 1,
"dateDay" : "26-6-2015",
"currency" : "USD"
},
{
"total" : 3820.8,
"no_of_orders" : 2,
"dateDay" : "26-6-2015",
"currency" : "GBP"
}
],
"ok" : 1
}