Map/reduce mongodb using two attributes - mongodb

I'm practicing with mongo using the sample db restaurants.
The db has the following structure:
{
"_id" : ObjectId("6035397d0076410d79b29bde"),
"address" : {
"building" : "522",
"coord" : [
-73.95171,
40.767461
],
"street" : "East 74 Street",
"zipcode" : "10021"
},
"borough" : "Manhattan",
"cuisine" : "American ",
"grades" : [
{
"date" : ISODate("2014-09-02T00:00:00Z"),
"grade" : "A",
"score" : 12
},
{
"date" : ISODate("2013-12-19T00:00:00Z"),
"grade" : "B",
"score" : 16
},
{
"date" : ISODate("2013-05-28T00:00:00Z"),
"grade" : "A",
"score" : 9
},
{
"date" : ISODate("2012-12-07T00:00:00Z"),
"grade" : "A",
"score" : 13
},
{
"date" : ISODate("2012-03-29T00:00:00Z"),
"grade" : "A",
"score" : 11
}
],
"name" : "Glorious Food",
"restaurant_id" : "40361521"
}
{
"_id" : ObjectId("6035397d0076410d79b29bdf"),
"address" : {
"building" : "284",
"coord" : [
-73.9829239,
40.6580753
],
"street" : "Prospect Park West",
"zipcode" : "11215"
},
"borough" : "Brooklyn",
"cuisine" : "American ",
"grades" : [
{
"date" : ISODate("2014-11-19T00:00:00Z"),
"grade" : "A",
"score" : 11
},
{
"date" : ISODate("2013-11-14T00:00:00Z"),
"grade" : "A",
"score" : 2
},
{
"date" : ISODate("2012-12-05T00:00:00Z"),
"grade" : "A",
"score" : 13
},
{
"date" : ISODate("2012-05-17T00:00:00Z"),
"grade" : "A",
"score" : 11
}
],
"name" : "The Movable Feast",
"restaurant_id" : "40361606"
}
What I'm trying to do is to get the total of cuisines per borought. So, if a borought has 5 resturants, but in this restaurants, 2 serve the same kind of food, my total should be 4.
I'm suposed to use map/reduce/finalize functions, but I can't figure out how.
All exemples I saw, in the map you have just one attribute to filter de data, but I need to group the restaurants of the same borough and then group e count by cuisine.
Can anyone help me? I've been tryng for a long time, didn't get enyware. The best I manage was to count the total of restaurants per borough.
Thank you.

Try this:
db.restaurants.aggregate([
// First group by "borough" and "cousine".
{
$group: {
_id: {
"borough": "$borough",
"cuisine": "$cuisine"
},
count: { $first: 1 }
}
},
// Second group by only "borough".
{
$group: {
_id: "$_id.borough",
count: { $sum: "$count" }
}
}
]);
Output:
/* 1 */
{
"_id" : "Brooklyn",
"count" : 1
},
/* 2 */
{
"_id" : "Manhattan",
"count" : 2
}
My test data:
/* 1 createdAt:2/24/2021, 11:35:10 PM*/
{
"_id" : ObjectId("6036955624f3423874ac9540"),
"borough" : "Manhattan",
"cuisine" : "Indian",
"restaurant_id" : "40361605"
},
/* 2 createdAt:2/24/2021, 11:35:10 PM*/
{
"_id" : ObjectId("6036955624f3423874ac953f"),
"borough" : "Brooklyn",
"cuisine" : "American",
"restaurant_id" : "40361606"
},
/* 3 createdAt:2/24/2021, 11:35:10 PM*/
{
"_id" : ObjectId("6036955624f3423874ac953e"),
"borough" : "Manhattan",
"cuisine" : "American",
"restaurant_id" : "40361522"
},
/* 4 createdAt:2/24/2021, 11:35:10 PM*/
{
"_id" : ObjectId("6036955624f3423874ac953d"),
"borough" : "Manhattan",
"cuisine" : "American",
"restaurant_id" : "40361521"
}

Related

why group sum qty by item qty not zero but it show many number with letter e "1.1102230246251565e-16" with aggregate mongodb?

Everyone please help me with sum qty by item, in fact It is zero but when I sum with aggregate it's always show the number like that 1.1102230246251565e-16 any solution to fix. you can see my items as below is my collection with aggregate.
Example it just sample data with aggregate please help me or any recommendation. I'm not sure with sum different with what to expect.
let data[
{
"_id" : ObjectId("5ca1d52e63102d00072fa433"),
"itemId" : "91",
"qty" : 10
},
{
"_id" : ObjectId("5cde757ba9b05421b2fd4c02"),
"itemId" : "91",
"qty" : 7
},
{
"_id" : ObjectId("5ccbca18b4448606bb6b32d9"),
"itemId" : "91",
"qty" : -10
},
{
"_id" : ObjectId("5ccbef392dee2a084cd54a59"),
"itemId" : "91",
"qty" : -6
},
{
"_id" : ObjectId("5ccbf5632dee2a084cd54bb3"),
"itemId" : "91",
"qty" : 20
},
{
"_id" : ObjectId("5ccc0ae7f2f55c0a0745fa3e"),
"itemId" : "91",
"qty" : -10
},
{
"_id" : ObjectId("5c9315ae1dfa340d69b85033"),
"itemId" : "91",
"qty" : -1
},
{
"_id" : ObjectId("5cccf4149e6bf007522a4569"),
"itemId" : "91",
"qty" : 35
},
{
"_id" : ObjectId("5cde7b03758b1a25055b9c4b"),
"itemId" : "91",
"qty" : -0.967
},
{
"_id" : ObjectId("5cde7b03758b1a25055b9c50"),
"itemId" : "91",
"qty" : -9
},
{
"_id" : ObjectId("5ccfa8380d4b880630c9c1b3"),
"itemId" : "91",
"qty" : -10
},
{
"_id" : ObjectId("5ccfa85d0d4b880630c9c1c7"),
"itemId" : "91",
"qty" : -5
},
{
"_id" : ObjectId("5ccfaf7c0d4b880630c9c1f5"),
"itemId" : "91",
"qty" : -5
},
{
"_id" : ObjectId("5c935b486f6338291f31f907"),
"itemId" : "91",
"qty" : -10
},
{
"_id" : ObjectId("5c9987c5ad6cb100076860b7"),
"itemId" : "91",
"qty" : 25
},
{
"_id" : ObjectId("5ccfe4a388ed8d07d6328f3e"),
"itemId" : "91",
"qty" : -20
},
{
"_id" : ObjectId("5c999660ad6cb100076860fe"),
"itemId" : "91",
"qty" : 25
},
{
"_id" : ObjectId("5cde73a8a9b05421b2fd4bff"),
"itemId" : "91",
"qty" : -1.033
},
{
"_id" : ObjectId("5ca424bac87f4f0007d833ba"),
"itemId" : "91",
"qty" : -10
},
{
"_id" : ObjectId("5cad54eb9c7a210007ac456a"),
"itemId" : "91",
"qty" : -20
},
{
"_id" : ObjectId("5cb03fc66554c600078fe7d4"),
"itemId" : "91",
"qty" : 20
},
{
"_id" : ObjectId("5cc65fbd122c9300076f9f44"),
"itemId" : "91",
"qty" : -5
},
{
"_id" : ObjectId("5cd152ba3790d300077bdc23"),
"itemId" : "91",
"qty" : -10
},
{
"_id" : ObjectId("5cd234653790d300077bdc7a"),
"itemId" : "91",
"qty" : -9
}
]
//Aggregate sum qty by item
data.aggregate([
{
$match: {itemId:'91'}
},
{
$group: {
_id: "$itemId",
onhand:{$sum:'$qty'}
}
}
]).toArray()
// And the result it is not zero but it show like that
//{
// "_id" : "91",
// "onhand" : 1.1102230246251565e-16
//}

Mongodb aggregate match value in array

i'm working with the restaurants db in mongo
{
"_id" : ObjectId("5c66fcf59e184ea712adfba6"),
"address" : {
"building" : "97-22",
"coord" : [
-73.8601152,
40.7311739
],
"street" : "63 Road",
"zipcode" : "11374"
},
"borough" : "Queens",
"cuisine" : "Jewish/Kosher",
"grades" : [
{
"date" : ISODate("2014-11-24T00:00:00.000Z"),
"grade" : "Z",
"score" : 20
},
{
"date" : ISODate("2013-01-17T00:00:00.000Z"),
"grade" : "A",
"score" : 13
},
{
"date" : ISODate("2012-08-02T00:00:00.000Z"),
"grade" : "A",
"score" : 13
},
{
"date" : ISODate("2011-12-15T00:00:00.000Z"),
"grade" : "B",
"score" : 25
}
],
"name" : "Tov Kosher Kitchen",
"restaurant_id" : "40356068"
}
I'm tryng to filter with match in aggregate. I want to check if any score in grades is greater than 5
db.runCommand({
aggregate: "restaurants",
pipeline : [
{$match: {"grades": {$anyElementTrue: {"score": {$gt:5}}}}}
but i'm getting this error:
"errmsg" : "unknown operator: $anyElementTrue",
thanks
Try with $eleMatch
db.restaurants.aggregate([{$match: {"grades": {$elemMatch: {"score": {$gt:5}}}}}])

Grouping in MongoDB Aggregate

I am starting with MongoDB and i find the Aggregate function hard to understand.
i have read many topics and tried many things, however i still don't get the results i am looking for.
I would like to group some things together to make a overview of the amount of things based on a few match parameters.
my DB:
{
"_id" : ObjectId("5943a4f015813165b6d2b79a"),
"productType" : "mail",
"productAmount" : 1,
"orderid" : "1497607274",
"location" : "99",
"sublocation" : "02",
"date" : ISODate("2017-01-01T09:01:13.000Z"),
"__v" : 0
}
/* 2 */
{
"_id" : ObjectId("5943a4f915813165b6d2b79c"),
"productType" : "mail",
"productAmount" : 1,
"orderid" : "1497607274",
"location" : "99",
"sublocation" : "01",
"date" : ISODate("2017-01-01T09:01:13.000Z"),
"__v" : 0
}
/* 3 */
{
"_id" : ObjectId("5943a4fe15813165b6d2b79e"),
"productType" : "mail",
"productAmount" : 1,
"orderid" : "1497607274",
"location" : "25",
"sublocation" : "01",
"date" : ISODate("2017-01-01T09:01:13.000Z"),
"__v" : 0
}
/* 4 */
{
"_id" : ObjectId("5943a56d15813165b6d2b7a0"),
"productType" : "mail",
"productAmount" : 1,
"orderid" : "1497607274",
"location" : "99",
"sublocation" : "01",
"date" : ISODate("2017-01-01T09:01:13.000Z"),
"__v" : 0
}
/* 5 */
{
"_id" : ObjectId("5943a971a367b069bb3e863c"),
"productType" : "mail",
"productAmount" : 1,
"orderid" : "1497607274",
"location" : "98",
"sublocation" : "01",
"date" : ISODate("2017-01-01T09:01:13.000Z"),
"__v" : 0
}
/* 6 */
{
"_id" : ObjectId("5943d824900fce1821c5845d"),
"productType" : "keychain",
"productAmount" : 1,
"orderid" : "1497607251",
"location" : "25",
"sublocation" : "01",
"date" : ISODate("2017-01-01T09:01:13.000Z")
}
/* 7 */
{
"_id" : ObjectId("5943d9ea900fce1821c5845e"),
"productType" : "mail",
"productAmount" : 1,
"orderid" : "1497607251",
"location" : "25",
"sublocation" : "02",
"date" : ISODate("2017-01-01T09:01:13.000Z")
}
my current query:
db.getCollection('products').aggregate([
{ $group: {
_id : {
"orderid" : "$orderid",
"location" : "$location",
"product" : "$productType",
"sublocation" : "$sublocation",
"date" : "$date",
"aant" : { "$sum" : "$productAmount"}
},
"aantal" : { "$sum" : 1},
"aantal2" : { "$sum" : "$productAmount"}
}
},
{
$group : {
_id : "$_id.product",
"productType" : {
"$push" : {
"loc" : "$_id.location",
"prodtype": "$_id.product",
"count": "$aantal2"},
},
"cnt": {"$sum" : "$aantal2"}
}
}
])
i would like to have this result:
{
Location: 25,
sublocation: 01,
<productTypeX> : <count the number of these products>,
<productTypeY> : <count the number of these products>,
<productTypeZ> : <count the number of these products>
},
{
Location: 25,
sublocation: 02,
<productTypeX> : <count the number of these products>,
<productTypeY> : <count the number of these products>,
<productTypeZ> : <count the number of these products>
}
or:
{
location: 25,
sublocation: 01,
products: [
{
<productTypeX> : <count>,
<productTypeY> : <count>,
<productTypeZ> : <count>
}
},
{
location: 25,
sublocation: 02
products: [
{
<productTypeX> : <count>,
<productTypeY> : <count>,
<productTypeZ> : <count>
}
}
if i get this to work i need to convert it to mongoose for NodeJS (tips are welcome)
Thanks in advance!

How to query mongodb with embedded document

Hi i'm practicing mongodb and I'm stuck with a problem. I'av the following set of documents.
{
"_id" : ObjectId("57cf9a134607674792dbad9e"),
"address" : {
"building" : "351",
"coord" : [
-73.9851356,
40.7676919
],
"street" : "West 57 Street",
"zipcode" : "10019"
},
"borough" : "Manhattan",
"cuisine" : "Irish",
"grades" : [
{
"date" : ISODate("2014-09-06T00:00:00.000Z"),
"grade" : "A",
"score" : 2
},
{
"date" : ISODate("2013-07-22T00:00:00.000Z"),
"grade" : "A",
"score" : 11
},
{
"date" : ISODate("2012-07-31T00:00:00.000Z"),
"grade" : "A",
"score" : 12
},
{
"date" : ISODate("2011-12-29T00:00:00.000Z"),
"grade" : "A",
"score" : 12
}
],
"name" : "Dj Reynolds Pub And Restaurant",
"restaurant_id" : "30191841"
}
I want to fetch list of all documents where zipcode is 10019
I'm following mongodb db tutorials and i've tried the following queries but nothing seems to work and i'm getting zero errors.
db.restaurants.find({address:{zipcode:10019}});
db.restaurants.find({"address.zipcode":10019})
zipcode is a string so your query should be
db.restaurants.find({ "address.zipcode": "10019" })
instead of
db.restaurants.find({ "address.zipcode": 10019 })

Simple update not working using positional $ operator

I'm just starting out with Mongo, and following the documentation here, I can't seem to update a value in a nested array when I apply the same technique.
This is my document:
{
"_id" : ObjectId("56d2cf8ee2b075667d4f0545"),
"address" : {
"building" : "522",
"coord" : [
-73.95171,
40.767461
],
"street" : "East 74 Street",
"zipcode" : "10021"
},
"borough" : "Manhattan",
"cuisine" : "American ",
"grades" : [
{
"date" : ISODate("2014-09-02T00:00:00Z"),
"grade" : "A",
"score" : 12
},
{
"grade" : "B",
"score" : 16,
"date" : ISODate("2013-12-19T00:00:00Z")
},
{
"date" : ISODate("2013-05-28T00:00:00Z"),
"grade" : "A",
"score" : 9
},
{
"date" : ISODate("2012-12-07T00:00:00Z"),
"grade" : "A",
"score" : 13
},
{
"date" : ISODate("2012-03-29T00:00:00Z"),
"grade" : "A",
"score" : 11
}
],
"name" : "Glorious Food",
"restaurant_id" : "40361521"
}
and this is my query:
db.restaurants.update(
{
_id: 'ObjectId("56d2cf8ee2b075667d4f0545")',
'grades.date': 'ISODate("2014-09-02T00:00:00Z")'
},
{
$set: { 'grades.$.score': 1 }
}
)
I'm sure I must have missed something obvious.
remove quotes from objectId and date field - please see below:
db.restaurants.update(
{
_id: ObjectId("56d2cf8ee2b075667d4f0545"),
"grades.date": ISODate("2014-09-02T00:00:00Z")
},
{
$set: { 'grades.$.score': 1 }
}
)