MongoDB SUM Of 2 Columns - mongodb

I have a following documents in my collection:
{ "_id" : ObjectId("5785e5649b732ab238cfc519"), "name" : "Apple", "category" : "Fruit", "price" : 100, "discount" : 5 }
{ "_id" : ObjectId("5785e5709b732ab238cfc51a"), "name" : "Orange", "category" : "Fruit", "price" : 90, "discount" : 5 }
{ "_id" : ObjectId("5785e5819b732ab238cfc51b"), "name" : "PineApple", "category" : "Fruit", "price" : 60, "discount" : 2 }
{ "_id" : ObjectId("5785e5969b732ab238cfc51c"), "name" : "Potatto", "category" : "Vegetable", "price" : 10, "discount" : 1 }
{ "_id" : ObjectId("5785e5c39b732ab238cfc51d"), "name" : "Cabbage", "category" : "Vegetable", "price" : 5, "discount" : 1 }
And Expected Result
{ "_id" : { "category" : "Vegetable" }, "total" : 15 }
And I am using mongoDB query to find the Sum of total with vegetable category as follows
db.stall.aggregate([{$group: {_id: {category: "Vegetable" }, total: {$sum: "$price"}}}]);
But I am getting the following result
{ "_id" : { "category" : "Vegetable" }, "total" : 265 }
How should I find the sum of total and discount columns with vegetable category.

I'm not sure if I'm getting your question right but this will filter the sume of Price and sum of Discount for Vegetable category.
db.stall.aggregate([
{
{$match : {category : "Vegetable"}},
{$group : {_id: "$category", sumOfTotal : {$sum : "$price"}, sumOfDiscount : {$sum : "$discount"}}}
}
])

Related

How to group by minimum value in nested arrays

I have a MongoDB collection with unique user traits and I'm trying to combine it with their orders, produce a new collection with the first order date and sum the total of orders by the user.
Given this example collection:
{
"_id" : 1,
"name" : "bob",
"orders" : [ { "date" : "2019-01-01", "amount" : 10 }, { "date" : "2019-01-02", "amount" : 10 } ]
}
{
"_id" : 1,
"name" : "lisa",
"orders" : [ { "date" : "2019-01-02", "amount" : 10 }, { "date" : "2019-01-03", "amount" : 15 } ]
}
this would be my desired output:
{
"_id" : 1,
"name" : "bob",
"first_order" : "2019-01-01",
"total_amount" : 20
}
{
"_id" : 2,
"name" : "lisa",
"first_order" : "2019-01-02",
"total_amount" : 25
}
Thank you

Find MongoDB docs where all sub-docs match criteria

I have some Product documents that each contain a list of ProductVariation sub-documents. I need to find all the Product docs where ALL their child ProductVariation docs have zero quantity.
Schemas look like this:
var Product = new mongoose.Schema({
name: String,
variations: [ProductVariation]
});
var ProductVariation = new mongoose.Schema({
type: String,
quantity: Number,
price: Number
});
I am a little new to mongodb, so even sure where to start here.
Try using $not wrapped around { "$gt" : 0 }:
> db.products.find()
{ "_id" : ObjectId("5b7cae558ff28edda6ba4a67"), "name" : "widget", "variations" : [ { "type" : "color", "quantity" : 0, "price" : 10 }, { "type" : "size", "quantity" : 0, "price" : 5 } ] }
{ "_id" : ObjectId("5b7cae678ff28edda6ba4a68"), "name" : "foo", "variations" : [ { "type" : "color", "quantity" : 2, "price" : 15 }, { "type" : "size", "quantity" : 0, "price" : 5 } ] }
{ "_id" : ObjectId("5b7cae7f8ff28edda6ba4a69"), "name" : "bar", "variations" : [ { "type" : "color", "quantity" : 0, "price" : 15 }, { "type" : "size", "quantity" : 1, "price" : 5 } ] }
> db.products.find({"variations.quantity": { "$not" : { "$gt" : 0 } } })
{ "_id" : ObjectId("5b7cae558ff28edda6ba4a67"), "name" : "widget", "variations" : [ { "type" : "color", "quantity" : 0, "price" : 10 }, { "type" : "size", "quantity" : 0, "price" : 5 } ] }
It can also take advantage of an index on { "variations.quantity" : 1 }.

Can't convert from BSON type string to Date on aggregation pipeline

I am using MongoDB 3.4.9, and I want to have monthly report w.r.t. customer info, and here are the Sample example mongodb records with nested items and error received is:
can't convert from BSON type string to Date
{
"_id" : ObjectId("59da6a331c7a9ac0b6674fe8"),
"date" : ISODate("2017-10-08T18:10:59.899Z"),
"items" : [
{
"quantity" : 1,
"price" : 47.11,
"desc" : "Item #1"
},
{
"quantity" : 2,
"price" : 42.0,
"desc" : "Item #2"
}
],
"custInfo" : "Tobias Trelle, gold customer"
}
{
"_id" : ObjectId("59da6a511c7a9ac0b6674fed"),
"date" : ISODate("2017-10-08T18:11:28.961Z"),
"items" : [
{
"quantity" : 1,
"price" : 47.11,
"desc" : "Item #1"
},
{
"quantity" : 2,
"price" : 42.0,
"desc" : "Item #2"
}
],
"custInfo" : "Tobias Trelle, gold customer"
}
{
"_id" : ObjectId("59da6a511c7a9ac0b6674ff0"),
"date" : ISODate("2017-10-08T18:11:29.133Z"),
"items" : [
{
"quantity" : 1,
"price" : 47.11,
"desc" : "Item #1"
},
{
"quantity" : 2,
"price" : 42.0,
"desc" : "Item #2"
}
],
"custInfo" : "Tobias Trelle, gold customer"
}
Here is the MongoDB query for calculating sum grouping by custInfo month wise
db.runCommand({aggregate:"order", pipeline :
[{$match : {$and : [{"date" : {$gte : ISODate("2016-10-08T18:10:59.899Z")}},
{"date" : {$lte : ISODate("2018-10-08T18:10:59.899Z")}}]}}
,
{ "$project" : { "custInfo" : 1 ,"count" : 1 , "date" : 1 ,
"duration" : {"$month" : [ "date"]}}},
{ "$group" : { "_id" :
{ "duration" : "$duration" , "custInfo" : "$custInfo"} ,"count" : { "$sum" : 1} }}
]}//,
//cursor:{batchSize:1000}
)
Please help where I was wrong.
Regards
Kris
I'm not sure why $month is considered to be "duration" here but in any event, you dropped a dollar sign off the field variable and the call to $month was a bit off. This should work:
{ "$project" : { "custInfo" : 1 ,
"count" : 1 ,
"date" : 1 ,
"duration" : {"$month" : "$date" } }}
Not related with your specific case, but with the generic solution to this BSON error...
Solve this problem with:
{"project: { "y.dateFieldName":
{"$cond":[{ $eq: [{$type: "$data.dateFieldName"},'date']},{"$year":"$data.dateFieldName"},-1]}}

how to get the aggregate sum on a set of fields with the same values using mongo

I am trying to find the sum of documents which have the same values on a set of fields using mongo shell, these are sample documents,
{
"id" : "1",
"date" : ISODate("2017-04-29T00:00:00.000Z"),
"amount" : 697,
"name" : "vendor1"
}
{
"id" : "2",
"date" : ISODate("2017-04-29T00:00:00.000Z"),
"amount" : 380
"name" : "vendor2"
}
{
"id" : "2",
"date" : ISODate("2017-04-29T00:00:00.000Z"),
"amount" : 380,
"name" : "vendor2"
}
{
"id" : "3",
"date" : ISODate("2017-04-29T00:00:00.000Z"),
"amount" : 702,
"name" : "vendor3"
}
{
"id" : "3",
"date" : ISODate("2017-04-29T00:00:00.000Z"),
"amount" : 702,
"name" : "vendor3"
}
the query I have tried is,
db.results.aggregate([
{$group:{'_id':{name:'$name', id:'$id', date:'$date', amount:'$amount',
count:{'$sum':1}}}},
{$match:{'count':{'$gt':1}}}])
but it fetched 0 records. Also I like to know how many such documents have been found, So I am wondering how to solve the issue.
You can use this.
db.results.aggregate([
{ $group:{'_id': {name:'$name', id:'$id', date:'$date', amount:'$amount'}
, count: {$sum: 1} } }
])
Result:
{ "_id" : { "name" : "vendor3", "id" : "3", "date" : ISODate("2017-04-29T00:00:00Z"), "amount" : 702 }, "count" : 2 }
{ "_id" : { "name" : "vendor2", "id" : "2", "date" : ISODate("2017-04-29T00:00:00Z"), "amount" : 380 }, "count" : 2 }
{ "_id" : { "name" : "vendor1", "id" : "1", "date" : ISODate("2017-04-29T00:00:00Z"), "amount" : 697 }, "count" : 1 }

Aggregate inside document in mongodb

I have document sales
db.sale.findOne({_id : ObjectId("52ea4dd29dbc7923107ddb97")})
{
"_id" : ObjectId("52ea4dd29dbc7923107ddb97"),
"firm" : ObjectId("52e56c009dbc794999ea5c3d"),
"patient" : {
"last" : "",
"first" : ""
},
"doc" : "",
"hospital" : "",
"discount" : 0,
"dd" : "",
"mode" : "cash",
"invoice" : "300114-undefined-1",
"items" : [
{
"bat" : "BJFE",
"narco" : 0,
"name" : "GDRNCCD",
"mrp" : 1,
"free" : 0,
"qty" : 1,
"item_discount" : 0,
"wpr" : 1,
"exp" : "1425168000000"
},
{
"bat" : "",
"narco" : 0,
"name" : "GDRN vbhjdsfb",
"mrp" : 1,
"free" : 0,
"qty" : 1,
"item_discount" : 0,
"wpr" : 0,
"exp" : "[object Object]"
},
{
"bat" : "",
"narco" : 0,
"name" : "GDRN vbhjdsfb",
"mrp" : 1,
"free" : 0,
"qty" : 1,
"item_discount" : 0,
"wpr" : 0,
"exp" : "[object Object]"
}
],
"date" : ISODate("2014-01-30T00:00:00Z"),
"mob" : "",
"email" : ""
}
How can I Aggregate total numbers if items in one field and sum up mrp *qty of all the items into one field.
I have read the mognodb aggregation but it only aggregates among group of matched documents not inside a single document. Is it possile?
{
"_id" : ObjectId("52ea4dd29dbc7923107ddb97"),
"firm" : ObjectId("52e56c009dbc794999ea5c3d"),
'total_items' : items.length,
"total" : mrp*qty of all items,
}
db.sales.aggregate(
{$unwind: "$items"},
{$project: {_id: 1,firm:1, total: {$multiply: ["$items.mrp", "$items.qty"]}}},
{$group: {_id: {"id":"$_id", firm:"$firm"}, count: {$sum:1} , total : {$sum:"$total"}}}
)
With a slight change : _id contains id and firm, you will need an extra projection to match your desired document, but I don't think it's important.
Plus, you can easily change to group by farm only
Thanks to Orid,I tried this,
db.sale.aggregate(
{ $match :{ firm :ObjectId("52e56c009dbc794999ea5c3d") } },
{$project : {day : {$dayOfMonth : '$date'},items :1,patient :1,invoice :1}},
{$match : {day: {$gte : new Date().getDate()}}},
{$unwind : "$items"},
{$project: {_id: 1,patient:1,invoice :1, total: {$multiply: ["$items.mrp", "$items.qty"]}}},
{$group: {_id: {"id":"$_id", invoice:"$invoice",patient :"$patient"}, count: {$sum:1} , total : {$sum:"$total"}}})
Result
{
"result" : [
{
"_id" : {
"id" : ObjectId("52eab6129dbc7923107ddbaf"),
"invoice" : "310114-undefined-1",
"patient" : {
"last" : "",
"first" : ""
}
},
"count" : 2,
"total" : 25
},
{
"_id" : {
"id" : ObjectId("52eab6129dbc7923107ddbb0"),
"invoice" : "310114-undefined-1",
"patient" : {
"last" : "",
"first" : ""
}
},
"count" : 1,
"total" : 1
},
{
"_id" : {
"id" : ObjectId("52eab6129dbc7923107ddbae"),
"invoice" : "310114-undefined-1",
"patient" : {
"last" : "",
"first" : ""
}
},
"count" : 2,
"total" : 5
}
],
"ok" : 1
}