How to get sum of elements using mongo? - mongodb

I have following json structure-
[{
cName:"A",
"vms" : [
{
"status":"off",
"name":"ds0",
"capacity":5
},
{
"name" : "ds1",
"status":"on",
"capacity":5
},
{
"name" : "ds2",
"status":"off",
"capacity":5
},
{
"name" : "ds3",
"status":"off",
"capacity":10
}
],
},
{
cName:"B",
"vms" : [
{
"name" : "ds4",
"status":"on",
"capacity":52
},
{
"name" : "ds3",
"status":"off",
"capacity":50
},
{
"name" : "ds5",
"status":"off",
"capacity":15
}
],
}
]
My expected output is following -
[{
"cName":"A",
"capacity":20,
},[{
"cName":"B",
"capacity":65,
}
]
I am using mongo aggregation to get output.
I am able to get cname and capacity using it but unable to get sum of capacity.
How do I get sum of capacity of vms using mongo aggregation??

If I understood you correctly
db.f.aggregate([
{
$unwind:"$vms"
},
{
$group:{
_id:"$cName",
capacity:{$sum:"$vms.capacity"}
}
},
{
$sort:{_id:1}
},{
$project:{
_id:0,
"cName":"$_id",
"capacity":1
}
}
])
Result:
{
"result" : [
{
"capacity" : 25,
"cName" : "A"
},
{
"capacity" : 117,
"cName" : "B"
}
],
"ok" : 1
}
I don't understand why in your example cName:A capacity = 20 (5+5+5+10) even cName:B...Maybe it's only the mock

Related

MongoDb find with nested array

Lets say I have this kind of collection
{
"_id" :"A",
"title" : "TITLE1",
"brand" : [
{
"brand_id" : "B",
"varients" : [
{
"name" : "RED ",
"price" : 5.0
}
]
},
{
"brand_id" : "C",
"varients" : [
{
"name" : "GREEN",
"price" : 5.0
}
]
},
{
"brand_id" : "D",
"varients" : [
{
"name" : "Others",
"price" : 0.0
}
]
}
],
}
I then want to select one and ONLY the nested data of variants. Have tried with the following statement without any success.
db.testing.findOne( {_id: "A", "brand.brand_id" : 'D'} )
Expected output
"varients" : [
{
"name" : "Others",
"price" : 0.0
}
]
Using findOne you can't get the subset or nest content of the document in the response, but yes using aggregation you can get it in a way you want it
Check out this aggregation pipeline:
[
{
'$match': {
'_id': 'A'
}
}, {
'$unwind': {
'path': '$brand'
}
}, {
'$match': {
'brand.brand_id': 'D'
}
}, {
'$project': {
'varients': '$brand.varients',
'_id': 0
}
}
]

How to write mongo query

How I can get the total number of seats available for a particular movie (seats present in all the theatres for that movie) from the mongodb schema below.
I need to write a mongo query to get the results
{
"_id" : ObjectId("5d637b5ce27c7d60e5c42ae7"),
"name" : "Bangalore",
"movies" : [
{
"name" : "KGF",
"theatres" : [
{
"name" : "PVR",
"seats" : 45
},
{
"name" : "IMAX",
"seats" : 46
}
]
},
{
"name" : "Avengers",
"theatres" : [
{
"name" : "IMAX",
"seats" : 50
}
]
}
],
"_class" : "com.BMS_mongo.ZZ_BMS_mongo_demo.Entity.CityInfo"
}
I have written this code :
db.cities.aggregate( [
{ "$unwind" : "$movies" }, { "$unwind" : "$theatres" } ,
{ "$group" : { _id : "$movies.theatre`enter code here`s.seats" ,
total : { "$sum" : "$seats" } }
}
] )
My schema:
The following query can get us the expected output:
db.collection.aggregate([
{
$unwind:"$movies"
},
{
$unwind:"$movies.theatres"
},
{
$group:{
"_id":"$movies.name",
"movie":{
$first:"$movies.name"
},
"totalSeats":{
$sum:"$movies.theatres.seats"
}
}
},
{
$project:{
"_id":0
}
}
]).pretty()
Data set:
{
"_id" : ObjectId("5d637b5ce27c7d60e5c42ae7"),
"name" : "Bangalore",
"movies" : [
{
"name" : "KGF",
"theatres" : [
{
"name" : "PVR",
"seats" : 45
},
{
"name" : "IMAX",
"seats" : 46
}
]
},
{
"name" : "Avengers",
"theatres" : [
{
"name" : "IMAX",
"seats" : 50
}
]
}
],
"_class" : "com.BMS_mongo.ZZ_BMS_mongo_demo.Entity.CityInfo"
}
Output:
{ "movie" : "Avengers", "totalSeats" : 50 }
{ "movie" : "KGF", "totalSeats" : 91 }
Query:
db.movie.aggregate([{ $unwind: { path: "$movies",} },
{ $unwind: { path: "$movies.theatres",} },
{ $group: { _id: "$movies.name", "moviename": { $first: "$movies.name" },
"totalSeats": { $sum: "$movies.theatres.seats" }} }])
I got the answer using this query ...
db.cities.aggregate( [
{ "$match" : { "name" : "Bangalore" } },
{ "$unwind" : "$movies" } ,
{ "$match" : {"movies.name" : "KGF"} },
{ "$unwind" : "$theatres" },
{ "$group" : { _id : "$movies.name", total : { "$sum" : "$movies.theatres.seats"
} } }
] )

How to take the duplicate records in mongodb

Here i have two document ,in this documents childNodes array ID is duplicate means , i want to take the userID and pedagogyID of the record,as per my documents second document under childNodes array 798 is coming duplicate, so i want to take the records
Documents
{
"userID" : "A",
"pedagogyID" : "100",
"summary" : {
"LearnProgress" : {
"childNodes" : [
{
"ID" : "123",
"status" : "in-progress"
},
{
"ID" : "456",
"status" : null
},
{
"ID" : "333",
"status" : null
}
],
}
}
}
{
"userID" : "B",
"pedagogyID" : "200",
"summary" : {
"LearnProgress" : {
"childNodes" : [
{
"ID" : "789",
"status" : "in-progress"
},
{
"ID" : "1010",
"status" : null
},
{
"ID" : "789",
"status" : null
}
],
}
}
}
Expected Output
{
"userID" : "B",
"pedagogyID" : "200",
}
MY Code
db.collectionname.aggregate(
[
{"$unwind":"$summary.LearnProgress.childNodes"},
{"$group":{
"_id":{"_id":"$_id","ID":"$summary.LearnProgress.childNodes.ID"},
"userID":{"$first":"$userID"},
"pedagogyID":{"$first":"$pedagogyID"},
"count":{"$sum":1}
}},
{"$match":{"count":{"$gt":1}}},
{"$group":{"_id":{"userID":"$userID","pedagogyID":"$pedagogyID"}}},
{"$replaceRoot":{"newRoot":"$_id"}}
],
{ allowDiskUse:true }
)
You can use below aggregation.
db.colname.aggregate([
{"$unwind":"$summary.LearnProgress.childNodes"},
{"$group":{
"_id":{"_id":"$_id","ID":"$summary.LearnProgress.childNodes.ID"},
"userID":{"$first":"$userID"},
"pedagogyID":{"$first":"$pedagogyID"},
"count":{"$sum":1}
}},
{"$match":{"count":{"$gt":1}}},
{"$group":{"_id":{"userID":"$userID","pedagogyID":"$pedagogyID"}}},
{"$replaceRoot":{"newRoot":"$_id"}}
],{"allowDiskUse":true})
db.collectionname.aggregate(
// Pipeline
[
// Stage 1
{
$unwind: {
path : "$summary.LearnProgress.childNodes",
}
},
// Stage 2
{
$group: {
_id:'$summary.LearnProgress.childNodes.ID',
count:{$sum:1},
pedagogyID:{$first:'$pedagogyID'},
userID:{$first:'$userID'}
}
},
// Stage 3
{
$match: {
count:{$gt:1}
}
},
// Stage 4
{
$project: {
userID:1,
pedagogyID:1,
_id:0
}
},
]
);

monogdb nested array items exact match

I have a collection as below what I want is to fetch the items that has exact match of Tag="dolore", I tried different ways but I am getting all the elements if any of the embedded element has tag as dolore
{
"_id" : 123,
"vendor" : "ut",
"boxes" : [
{
"boxRef" : 321,
"items" : [
{
"Tag" : "dolore",
},
{
"Tag" : "irure",
},
{
"Tag" : "labore",
}
]
},
{
"boxRef" : 789,
"items" : [
{
"Tag" : "incididunt",
},
{
"Tag" : "magna",
},
{
"Tag" : "laboris",
}
]
},
{
"boxRef" : 456,
"items" : [
{
"Tag" : "reprehenderit",
},
{
"Tag" : "reprehenderit",
},
{
"Tag" : "enim",
}
]
}
]
}
If you are expecting to get only the matching embedded documents you have $unwind, $match and then $group to reverse the $unwind. Like this:
db.getCollection('collectionName').aggregate([
{
$unwind:"$boxes"
},
{
$unwind:"$boxes.items"
},
{
$match:{
"boxes.items.Tag":"dolore"
}
},
{
$group:{
_id:{
boxRef:"$boxes.boxRef",
_id:"$_id"
},
vendor:{
"$first":"$vendor"
},
boxRef:{
"$first":"$boxes.boxRef"
},
items:{
$push:"$boxes.items"
}
}
},
{
$group:{
_id:"$_id._id",
vendor:{
"$first":"$vendor"
},
boxes:{
$push:{
boxRef:"$boxRef",
items:"$items"
}
}
}
},
])
Output:
{
"_id" : 123.0,
"vendor" : "ut",
"boxes" : [
{
"boxRef" : 321.0,
"items" : [
{
"Tag" : "dolore"
}
]
}
]
}

mongodb aggregation match multiple $and on the same field

i have a document like this :
{
"ExtraFields" : [
{
"value" : "print",
"fieldID" : ObjectId("5535627631efa0843554b0ea")
},
{
"value" : "14",
"fieldID" : ObjectId("5535627631efa0843554b0eb")
},
{
"value" : "POLYE",
"fieldID" : ObjectId("5535627631efa0843554b0ec")
},
{
"value" : "30",
"fieldID" : ObjectId("5535627631efa0843554b0ed")
},
{
"value" : "0",
"fieldID" : ObjectId("5535627631efa0843554b0ee")
},
{
"value" : "0",
"fieldID" : ObjectId("5535627731efa0843554b0ef")
},
{
"value" : "0",
"fieldID" : ObjectId("5535627831efa0843554b0f0")
},
{
"value" : "42",
"fieldID" : ObjectId("5535627831efa0843554b0f1")
},
{
"value" : "30",
"fieldID" : ObjectId("5535627831efa0843554b0f2")
},
{
"value" : "14",
"fieldID" : ObjectId("5535627831efa0843554b0f3")
},
{
"value" : "19",
"fieldID" : ObjectId("5535627831efa0843554b0f4")
}
],
"id" : ObjectId("55369e60733e4914550832d0"), "title" : "A product"
}
what i want is to match one or more sets from the ExtraFields array. For example, all the products that contain the values print and 30. Since a value may be found in more than one fieldID (like 0 or true) we need to create a set like
WHERE (fieldID : ObjectId("5535627631efa0843554b0ea"), value : "print")
Where i'm having problems is when querying more than one fields. The pipeline i came up with is :
db.products.aggregate([
{'$unwind': '$ExtraFields'},
{
'$match': {
'$and': [{
'$and': [{'ExtraFields.value': {'$in': ["A52A2A"]}}, {
'ExtraFields.fieldID': ObjectId("5535627631efa0843554b0ea")
}]
}
,
{
'$and': [{'ExtraFields.value': '14'}, {'ExtraFields.fieldID': ObjectId("5535627631efa0843554b0eb")}]
}
]
}
},
]);
This returns zero results, but this is what i want to do in theory. Match all items that contain set 1 AND all that contain set 2.
The end result should look like a faceted search output :
[
{
"_id" : {
"values" : "18",
"fieldID" : ObjectId("5535627831efa0843554b0f3")
},
"count" : 2
},
{
"_id" : {
"values" : "33",
"fieldID" : ObjectId("5535627831efa0843554b0f2")
},
"count" : 1
}
]
Any ideas?
You could try the following aggregation pipeline
db.products.aggregate([
{
"$match": {
"ExtraFields.value": { "$in": ["A52A2A", "14"] },
"ExtraFields.fieldID": {
"$in": [
ObjectId("5535627631efa0843554b0ea"),
ObjectId("5535627631efa0843554b0eb")
]
}
}
},
{
"$unwind": "$ExtraFields"
},
{
"$match": {
"ExtraFields.value": { "$in": ["A52A2A", "14"] },
"ExtraFields.fieldID": {
"$in": [
ObjectId("5535627631efa0843554b0ea"),
ObjectId("5535627631efa0843554b0eb")
]
}
}
},
{
"$group": {
"_id": {
"value": "$ExtraFields.value",
"fieldID": "$ExtraFields.fieldID"
},
"count": {
"$sum": 1
}
}
}
])
With the sample document provided, this gives the output:
/* 1 */
{
"result" : [
{
"_id" : {
"value" : "14",
"fieldID" : ObjectId("5535627631efa0843554b0eb")
},
"count" : 1
}
],
"ok" : 1
}