Aggregate inside document in mongodb - 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
}

Related

Is it possible to input the result of one query as a condition in another query MongoDB

This was my query on MySQL:
select date, AVG(retail_and_recreation_percent_change_from_baseline),
AVG(grocery_and_pharmacy_percent_change_from_baseline),
AVG(workplaces_percent_change_from_baseline)
from global_mobility_report
where date >=
(select date
from owid_covid_data
where location like "Indonesia"
and CAST(total_cases as signed) > 20000
order by date
limit 1)
and country_region like "Indonesia"
group by date
order by date
I wanted to do something similar on MongoDB but I had to take 2 steps:
Step 1: Find the date
db.ovid2.aggregate([
{$match:{"location":"Indonesia"}},
{$match:{"total_cases":{$gt:20000}}},
{$sort:{date:1}},
{$project:{_id:0, date:1}}
{$limit:1}
])
output: ISODate("2020-05-22T00:00:00.000+08:00")
Step 2: Manually input the date and continue with the rest of the query
db.mobility.aggregate([
{$match:{"country_region":"Indonesia"}},
{$match:{"date":{$gte:ISODate("2020-05-22T00:00:00.000+08:00")}}},
{$group:{_id:"$date",
AvgRandR:{$avg:"$retail_and_recreation_percent_change_from_baseline"},
AvgGandP:{$avg:"$grocery_and_pharmacy_percent_change_from_baseline"},
AvgW:{$avg:"$workplaces_percent_change_from_baseline"}}},
{$sort:{_id:1}}
])
Is there an easier way to go about doing this? I realize this is not optimal especially if the question changes and Step 1 returns multiple outputs (say over 100). This means I would have to type a 100 different values into step 2?
Here are some sample documents:
collection: mobility
{
"_id" : ObjectId("5f49fd6a3acddb5eec4427bb"),
"country_region_code" : "ID",
"country_region" : "Indonesia",
"sub_region_1" : "",
"sub_region_2" : "",
"metro_area" : "",
"iso_3166_2_code" : "",
"census_fips_code" : "",
"date" : ISODate("2020-02-15T08:00:00.000+08:00"),
"retail_and_recreation_percent_change_from_baseline" : -2,
"grocery_and_pharmacy_percent_change_from_baseline" : -2,
"parks_percent_change_from_baseline" : -8,
"transit_stations_percent_change_from_baseline" : 1,
"workplaces_percent_change_from_baseline" : 5,
"residential_percent_change_from_baseline" : 1
},
{
"_id" : ObjectId("5f49fd6a3acddb5eec44281f"),
"country_region_code" : "ID",
"country_region" : "Indonesia",
"sub_region_1" : "",
"sub_region_2" : "",
"metro_area" : "",
"iso_3166_2_code" : "",
"census_fips_code" : "",
"date" : ISODate("2020-05-25T08:00:00.000+08:00"),
"retail_and_recreation_percent_change_from_baseline" : -40,
"grocery_and_pharmacy_percent_change_from_baseline" : -17,
"parks_percent_change_from_baseline" : -16,
"transit_stations_percent_change_from_baseline" : -59,
"workplaces_percent_change_from_baseline" : -70,
"residential_percent_change_from_baseline" : 19
},
{
"_id" : ObjectId("5f49fd6a3acddb5eec4428db"),
"country_region_code" : "ID",
"country_region" : "Indonesia",
"sub_region_1" : "Aceh",
"sub_region_2" : "",
"metro_area" : "",
"iso_3166_2_code" : "ID-AC",
"census_fips_code" : "",
"date" : ISODate("2020-05-22T08:00:00.000+08:00"),
"retail_and_recreation_percent_change_from_baseline" : -4,
"grocery_and_pharmacy_percent_change_from_baseline" : 33,
"parks_percent_change_from_baseline" : -10,
"transit_stations_percent_change_from_baseline" : -33,
"workplaces_percent_change_from_baseline" : -31,
"residential_percent_change_from_baseline" : 9
}
collection: ovid2
{
"_id" : ObjectId("5f4a06e23acddb5eec55a4aa"),
"iso_code" : "IDN",
"continent" : "Asia",
"location" : "Indonesia",
"date" : ISODate("2020-05-22T00:00:00.000+08:00"),
"total_cases" : 20162,
"new_cases" : 973,
"new_cases_smoothed" : 593.714,
"total_deaths" : 1278,
"new_deaths" : 36,
"new_deaths_smoothed" : 33.571,
"total_cases_per_million" : 73.712,
"new_cases_per_million" : 3.557,
"new_cases_smoothed_per_million" : 2.171,
"total_deaths_per_million" : 4.672,
"new_deaths_per_million" : 0.132,
"new_deaths_smoothed_per_million" : 0.123,
"new_tests" : 0,
"total_tests" : 168969,
"total_tests_per_thousand" : 0.618,
"new_tests_per_thousand" : 0,
"new_tests_smoothed" : 5273,
"new_tests_smoothed_per_thousand" : 0.019,
"tests_per_case" : 8.881,
"positive_rate" : 0.113,
"tests_units" : NaN,
"stringency_index" : 71.76,
"population" : 273523621,
"population_density" : 145.725,
"median_age" : 29.3,
"aged_65_older" : 5.319,
"aged_70_older" : 3.053,
"gdp_per_capita" : 11188.744,
"extreme_poverty" : 5.7,
"cardiovasc_death_rate" : 342.864,
"diabetes_prevalence" : 6.32,
"female_smokers" : 2.8,
"male_smokers" : 76.1,
"handwashing_facilities" : 64.204,
"hospital_beds_per_thousand" : 1.04,
"life_expectancy" : 71.72
},
{
"_id" : ObjectId("5f4a06e23acddb5eec55a420"),
"iso_code" : "IDN",
"continent" : "Asia",
"location" : "Indonesia",
"date" : ISODate("2020-01-05T00:00:00.000+08:00"),
"total_cases" : 0,
"new_cases" : 0,
"new_cases_smoothed" : 0,
"total_deaths" : 0,
"new_deaths" : 0,
"new_deaths_smoothed" : 0,
"total_cases_per_million" : 0,
"new_cases_per_million" : 0,
"new_cases_smoothed_per_million" : 0,
"total_deaths_per_million" : 0,
"new_deaths_per_million" : 0,
"new_deaths_smoothed_per_million" : 0,
"new_tests" : 0,
"total_tests" : 0,
"total_tests_per_thousand" : 0,
"new_tests_per_thousand" : 0,
"new_tests_smoothed" : 0,
"new_tests_smoothed_per_thousand" : 0,
"tests_per_case" : 0,
"positive_rate" : 0,
"tests_units" : 0,
"stringency_index" : 5.56,
"population" : 273523621,
"population_density" : 145.725,
"median_age" : 29.3,
"aged_65_older" : 5.319,
"aged_70_older" : 3.053,
"gdp_per_capita" : 11188.744,
"extreme_poverty" : 5.7,
"cardiovasc_death_rate" : 342.864,
"diabetes_prevalence" : 6.32,
"female_smokers" : 2.8,
"male_smokers" : 76.1,
"handwashing_facilities" : 64.204,
"hospital_beds_per_thousand" : 1.04,
"life_expectancy" : 71.72
},
{
"_id" : ObjectId("5f4a06e63acddb5eec55fbf3"),
"iso_code" : "ZWE",
"continent" : "Africa",
"location" : "Zimbabwe",
"date" : ISODate("2020-03-21T00:00:00.000+08:00"),
"total_cases" : 1,
"new_cases" : 1,
"new_cases_smoothed" : 0,
"total_deaths" : 0,
"new_deaths" : 0,
"new_deaths_smoothed" : 0,
"total_cases_per_million" : 0.067,
"new_cases_per_million" : 0.067,
"new_cases_smoothed_per_million" : 0,
"total_deaths_per_million" : 0,
"new_deaths_per_million" : 0,
"new_deaths_smoothed_per_million" : 0,
"new_tests" : 0,
"total_tests" : 0,
"total_tests_per_thousand" : 0,
"new_tests_per_thousand" : 0,
"new_tests_smoothed" : 0,
"new_tests_smoothed_per_thousand" : 0,
"tests_per_case" : 0,
"positive_rate" : 0,
"tests_units" : 0,
"stringency_index" : 27.78,
"population" : 14862927,
"population_density" : 42.729,
"median_age" : 19.6,
"aged_65_older" : 2.822,
"aged_70_older" : 1.882,
"gdp_per_capita" : 1899.775,
"extreme_poverty" : 21.4,
"cardiovasc_death_rate" : 307.846,
"diabetes_prevalence" : 1.82,
"female_smokers" : 1.6,
"male_smokers" : 30.7,
"handwashing_facilities" : 36.791,
"hospital_beds_per_thousand" : 1.7,
"life_expectancy" : 61.49
}
You can try,
$match your required conditions
$lookup with owid_covid_data collection using aggregation pipeline and get result in owid_covid_data field,
$match your required conditions
$project to required fields
$sort by date ascending order
$limit number 1 document to return
$match date condition
$unwind deconstruct owid_covid_data array, this will remove empty result document
$group by date and average fields
$sort by date ascending order
db.global_mobility_report.aggregate([
{ $match: { country_region: "Indonesia" } },
{
$lookup: {
from: "owid_covid_data",
let: { date: "$date" },
pipeline: [
{
$match: {
location: "Indonesia",
total_cases: { $gt: 20000 }
}
},
{ $project: { _id: 0, date: 1 } },
{ $sort: { date: 1 } },
{ $limit: 1 },
{ $match: { $expr: { $gte: ["$$date", "$date"] } } }
],
as: "owid_covid_data"
}
},
{ $unwind: "$owid_covid_data" },
{
$group: {
_id: "$date",
AvgRandR: { $avg: "$retail_and_recreation_percent_change_from_baseline" },
AvgGandP: { $avg: "$grocery_and_pharmacy_percent_change_from_baseline" },
AvgW: { $avg: "$workplaces_percent_change_from_baseline" }
}
},
{ $sort: { _id: 1 } }
])
Playground

Query to group distinct values and show sum of array values in mongodb

I wanted to group by cart.name and find the sum of cart.qty in mongodb. Below is sample document
{
"_id" : ObjectId("581323379ae5e607645cb485"),
"cust" : {
"name" : "Customer 1",
"dob" : "09/04/1989",
"mob" : 999999999,
"loc" : "Karimangalam",
"aadhar" : {
}
},
"cart" : [
{
"name" : "Casual Shirt",
"qty" : 1,
"mrp" : 585,
"discperc" : 10,
"fit" : null,
"size" : "L"
},
{
"name" : "Casual Shirt",
"qty" : 1,
"mrp" : 500,
"discperc" : 0,
"fit" : null,
"size" : "L"
},
{
"name" : "Cotton Pant",
"qty" : 1,
"mrp" : 850,
"discperc" : 0,
"fit" : null,
"size" : "34"
},
{
"name" : "Cotton Pant",
"qty" : 1,
"mrp" : 1051,
"discperc" : 10,
"fit" : null,
"size" : "34"
}
],
"summary" : {
"bill" : 2822.4,
"qty" : 4,
"mrp" : 2986,
"received" : "2800",
"balance" : -22.40000000000009
},
"createdAt" : ISODate("2016-10-28T10:06:47.367Z"),
"updatedAt" : ISODate("2016-10-28T10:06:47.367Z")
}
There are many document like this. I want the output as below distinct product name (cart.name) and its total qty
{Casual Shirt , 30},
{Cotton Pant , 10},
{T-Shirt , 15},
{Lower , 12}
Here is my query trying to group by cart.name and sum qty
db.order.aggregate( [
{ $unwind: "$cart" },
{ $group: {
_id: "$cart.name",
totalQTY: { $sum:"$cart.qty"},
count: { $sum: 1 }
}
}
] )
but it displays wrong totalQty values for each product name. I checked manually.
Please give me the correct query.
> db.collection.aggregate([
... { $unwind: "$cart" },
... { $group: { "_id": "$cart.name", totalQTY: { $sum: "$cart.qty" }, count: { $sum: 1 } } }
... ])
I get the following result:
{ "_id" : "Cotton Pant", "totalQTY" : 2, "count" : 2 }
{ "_id" : "Casual Shirt", "totalQTY" : 11, "count" : 2 }
I'm not sure what you're looking for, it looks like your aggregation pipeline is correct. (Note I changed the Casual Shirt Quantity to be 10 and 1 respectively)

MongoDB SUM Of 2 Columns

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

Mongodb aggregation: how to use unwind->group->project multiple times

I have an orders collection where I need to calculate some sums from multiple sub-arrays arrays but I can't figure out how to loose the multiplied items that the double unwind creates.
db.Orders.aggregate(
{$unwind: "$items"},
{$unwind: "$shipping"},
{$group: {
_id: {
year: { '$year': '$createdAt' },
month: { '$month': '$createdAt' },
day: { '$dayOfMonth': '$createdAt' }
},
mainItems: { $addToSet: '$items' },
totalSales: {$sum: {
$multiply: ["$items.quantity", "$items.variants.price"]
}},
averageSales: {$avg: {$multiply: ["$items.quantity", "$items.variants.price"]}},
/* this will not sum the individial orders because the unwind
* created multiple document per order*/
ordersPlaced: {$sum: 1},
itemsPurchased: {$sum: "$items.quantity"},
totalRefundAmount: {$sum: 0},
chargedForShipping: {$sum: "$shipping.shipmentMethod.rate"}
}}
)
If I take out the shipping from the unwind and the group the query will return the correct values except for the chargedForShipping (0 since it's unwinded) and ordersPlaces which will still be more than expected (but I also need the shipping information and even more additional ones that I took out for easier understanding).
Sample data:
[{
"_id" : "xK29ZHxGcYvgWgx5p",
"sessionId" : "yw7e9G7uBzYTy9Grq",
"userId" : "fZREMm2DmsnMosMKj",
"shopId" : "oiqQDnuBwabj44q2o",
"billing" : [
{
"shopId" : "oiqQDnuBwabj44q2o",
"_id" : "9TMJj9w65MmAkgg27",
"paymentMethod" : {
"amount" : 22.45,
"status" : "settled",
"mode" : "capture",
"transactionId" : "AP",
"createdAt" : ISODate("2016-02-15T13:44:35.116Z"),
"transactions" : [
{ type:"refund", amount:5}
]
}
},
{
"shopId" : "9YfkXWyCci8fN43Pj",
"_id" : "RwW8xMnFzQqdTpqtg",
"paymentMethod" : {
"createdAt" : ISODate("2016-02-15T13:44:35.116Z")
}
},
{
"shopId" : "SgXWPKGJkxBw6qsbT",
"_id" : "ASizt6BtkxpCxgEJn",
"paymentMethod" : {
"createdAt" : ISODate("2016-02-15T13:44:35.116Z")
}
}
],
"shipping" : [
{
"_id" : "yXb5T5zLuxPYmgoT5",
"shipmentMethod" : {
"name" : "Continental US",
"_id" : "womiJX2QZBFQQWFur",
"rate" : 9.949999999999999,
"shopId" : "9YfkXWyCci8fN43Pj",
},
"items" : [
{
"_id" : "48s9bmDfrRMqnkije",
"productId" : "KXtF5xqERWJsXk2yP",
"shopId" : "SgXWPKGJkxBw6qsbT",
"variantId" : "YQDHuyPHbhx4wruZx",
"quantity" : 1
}
],
"packed" : false,
"shipped" : false,
}
],
"items" : [
{
"_id" : "hhuiGFTBkLACLpPjQ",
"shopId" : "9YfkXWyCci8fN43Pj",
"productId" : "sDYNXMrnRJiyQ8gex",
"quantity" : 1,
"variants" : {
"_id" : "muJi6Bqnq2CD8B7AR",
"price" : 2.5,
"title" : "egy",
"weight" : 23,
},
"type" : "simple",
},
{
"_id" : "48s9bmDfrRMqnkije",
"shopId" : "SgXWPKGJkxBw6qsbT",
"productId" : "KXtF5xqERWJsXk2yP",
"quantity" : 1,
"variants" : {
"_id" : "YQDHuyPHbhx4wruZx",
"title" : "Bogi varinat title",
"price" : 10,
"type" : "variant",
"compareAtPrice" : 100000,
"weight" : 100,
},
"type" : "simple",
}
],
"email" : "test#user.com",
"createdAt" : ISODate("2016-02-15T13:44:35.091Z"),
"updatedAt" : ISODate("2016-02-15T14:24:55.174Z")
}]
What I would need is orderTotal per month, shippingTotal per month, totalRefunded per month, average sales per month. The issue is one I need from the items sub-array the other from the shipping sub-array and the third from the billing sub-array that is why I have issues with the unwind.

MongoDB aggregate $match and $group with $sum

i have a collection with documents like this:
{
"Company" : "4433",
"Descripcion" : "trabajo",
"Referencia" : "11817",
"HoraImportado" : "15:54",
"ImportedOd" : "2014-05-20T13:54:28.493Z",
"Items" : [],
"Notes" : [
{
"_id" : ObjectId("537b5ea4c61b1d1743f43420"),
"NoteDateTime" : "2014-05-20T13:54:44.418Z",
"Description" : "nota",
"IsForTechnician" : true,
"Username" : "admin"
},
{
"_id" : ObjectId("537c4a549e956f77ab8c7c38"),
"NoteDateTime" : ISODate("2014-05-21T06:40:20.299Z"),
"Description" : "ok",
"IsForTechnician" : true,
"Username" : "admin"
}
],
"OrderState" : "Review",
"SiniestroDe" : "Emergencia",
"Technicians" : [
{
"TechnicianId" : ObjectId("53465f9d519c94680327965d"),
"Name" : "Administrator",
"AssignedOn" : ISODate("2014-05-20T13:54:44.373Z"),
"RemovedOn" : null
}
],
"TechniciansHistory" : [
{
"TechnicianId" : ObjectId("53465f9d519c94680327965d"),
"Name" : "Administrator",
"AssignedOn" : ISODate("2014-05-20T13:54:44.373Z"),
"RemovedOn" : null
},
{
"Name" : "Nuevo",
"AssignedOn" : ISODate("2014-05-20T13:54:44.373Z"),
"RemovedOn" : null,
"TechnicianId" : ObjectId("5383577a994be8b9a9e3f01e")
}
],
"Telefonos" : "615554006",
"_id" : ObjectId("537b5ea4c61b1d1743f4341f"),
"works" : [
{
"code" : "A001",
"name" : "Cambiar bombilla",
"orderId" : "537b5ea4c61b1d1743f4341f",
"price" : "11",
"ID" : 33,
"lazyLoaded" : true,
"status" : 0,
"Date" : ISODate("2014-05-21T06:40:20.299Z"),
"TechnicianId" : "53465f9d519c94680327965d",
"_id" : ObjectId("537c4a549e956f77ab8c7c39")
},
{
"code" : "A001",
"name" : "Cambiar bombilla",
"orderId" : "537b5ea4c61b1d1743f4341f",
"price" : "11",
"ID" : 34,
"lazyLoaded" : true,
"status" : 0,
"Date" : ISODate("2014-05-21T06:40:20.299Z"),
"TechnicianId" : "53465f9d519c94680327965d",
"_id" : ObjectId("537c4a549e956f77ab8c7c3a")
}
]
}
Now i want to get the works for a selected TechnicianId array, group by TechnicianId and get the sum of the works.price for each technician.+
I try with this:
db.orders.aggregate([
{ $match: { 'works.TechnicianId': {$in:['53465f9d519c94680327965d']}}},
{ $group: { _id: "$works.TechnicianId",total:{$sum:'$works.price'}}},
])
And this is the result:
{
"result" : [
{
"_id" : [
"53465f9d519c94680327965d",
"53465f9d519c94680327965d"
],
"total" : 0
}
],
"ok" : 1
}
The total its the $sum but its 0 but should be 44.
Try adding unwind,
db.orders.aggregate([
{ $match: { 'works.TechnicianId': {$in:['53465f9d519c94680327965d']}}},
{ $unwind: "$works" },
{ $group: { _id: "$works.TechnicianId",total:{$sum:'$works.price'}}},
])
Look here for more info : http://docs.mongodb.org/manual/reference/operator/aggregation/unwind/
The price value is a string. $sum only operates on Numbers.
I've checked this by running the following:
db.foo.insert({"cost": "1"})
db.foo.insert({"cost": "2"})
db.foo.insert({"cost": "3"})
db.foo.insert({"cost": 4})
db.foo.insert({"cost": 5})
db.foo.aggregate([{$group: {_id: null, cost: {$sum: "$cost"}}}])
{ "result" : [ { "_id" : null, "cost" : 9 } ], "ok" : 1 }
According to this answer, you can't cast values in normal Mongo queries, so you can't change the string to a number inline.
You should either update all values to a Number datatype or use map-reduce. I'd go for the former.
If the value is a string to prevent floating point errors, consider multiplying by 100 to store the value in cents: "10.50" --> 1050
As Lalit Agarwal indicated, you'll also need to unwind the array of works. Example of what happens if you don't:
db.bar.insert({"works": [{price: 10}]})
db.bar.insert({"works": [{price: 20}, {price: 30}]})
db.bar.insert({"works": [{price: 40}, {price: 50}]})
db.bar.aggregate([
{$group: {_id: null, total: {$sum: "$works.price"} }}
])
{ "result" : [ { "_id" : null, "total" : 0 } ], "ok" : 1 }
db.bar.aggregate([
{$unwind: "$works"},
{$group: {_id: null, total: {$sum: "$works.price"} }}
])
{ "result" : [ { "_id" : null, "total" : 150 } ], "ok" : 1 }
What $unwind does is make 5 documents out of the initial 3, all with a single value in the works field. It then groups and sums them.
db.inventory.insert(
{
item: “ABC1”,
details: {
model: “14Q3”,
manufacturer: “XYZ Company”
},
stock: [ { size: “S”, qty: 25 }, { size: “M”, qty: 50 } ],
category: “clothing”
}
)