How to get value of field in array mongodb - mongodb

let's assume i have database structure as;
{
name: "alex",
age: 21,
school: [
{grade: 45, class: "elementary school", name: "blabla"},
{grade: 89, class: "high school", name: "blabla2"},
{grade: 12, class: "college", name: "blabla3"}
]
},
{
name: "felix",
age: 45,
school: [
{grade: 12, class: "elementary school", name: "bla"},
{grade: 45, class: "high school", name: "bla2"},
{grade: 16, class: "college", name: "bla3"}
]
}
what i want to do is get the school name for each name
{
name: alex,
school: ["blabla", "blabla2", "blabla3"]
},
{
name: felix,
school: ["bla", "bla2", "bla3"]
}
To be able achieve this,
db.collection.aggregate([
{group: {_id: "$name", school: {$addToSet: {"$school.name"}}}}
])
But couldn't achieve. What should I modify?

just unwinf the school array before grouping with a $unwind stage like this :
db.collection.aggregate([
{$unwind: "$school"},
{$group: {_id: "$name", school: {$addToSet: "$school.name"}}}
])
output:
{ "_id" : "felix", "school" : [ "bla3", "bla2", "bla" ] }
{ "_id" : "alex", "school" : [ "blabla3", "blabla2", "blabla" ] }

Related

How to add a particular value for all records in the collection using aggregation

How to add a particular value for all records in the collection using aggregation :
Have a collection with data :
[
{
_id: "bmasndvhjbcw",
name: "lucas",
occupation: "scientist",
present_working:true,
age: 55,
location: "texas",
date:2019-11-25T01:00:00.000+00:00
},
{
_id: "bmasndvhjbcx",
name: "mark",
occupation: "scientist",
age: 45,
location: "texas",
date:2019-11-25T01:00:00.000+00:00
},
{
_id: "bmasndvhjbcq",
name: "cooper",
occupation: "physicist",
age: 69,
location: "texas",
date:2019-11-25T01:00:00.000+00:00
}
]
if date column exists for any of the records present_working:true should be added in the collection for the records
expected output:
[
{
_id: "bmasndvhjbcw",
name: "lucas",
occupation: "scientist",
present_working:true,
age: 55,
location: "texas",
date:2019-11-25T01:00:00.000+00:00
},
{
_id: "bmasndvhjbcx",
name: "mark",
occupation: "scientist",
present_working:true,
age: 45,
location: "texas",
date:2019-11-25T01:00:00.000+00:00
},
{
_id: "bmasndvhjbcq",
name: "cooper",
occupation: "physicist",
present_working:true,
age: 69,
location: "texas",
date:2019-11-25T01:00:00.000+00:00
}
]
There is no need to use aggregation for this.
You can do it simply this way:
collection.updateMany({
date: {
$exists: true
}
}, {
$set: {
present_working: true
}
})
If you want to do it with the aggregation framework:
collection.aggregate(
[
{
"$match" : {
"date" : {
$exists: true
}
}
},
{
"$addFields" : {
"present_working" : true
}
}
]
)
So if you wanted to return conditionally add a field based upon existence of other field in aggregation while reading data from database then try below query :
/** If `date` exists then it will add the field & assign value to true else `$$REMOVE` will help to not add the field at all,
* Additionally if you're ok to add this new field for docs where `date : null` then replace `$gt` with `$gte` */
db.collection.aggregate([
{
$addFields: {
present_working: { $cond: [ { "$gt": [ "$date", null ] }, true, "$$REMOVE" ] }
}
}
])
Test : mongoplayground
Ref : aggregation-pipeline

Remove a particular field for all documents in a collection using aggregation in mongoDB

How to Remove a particular value for all records in the collection using aggregation :
Have a collection with data :
[
{
_id: "bmasndvhjbcw",
name: "lucas",
occupation: "scientist",
present_working:true,
age: 55,
location: "texas"
},
{
_id: "bmasndvhjbcx",
name: "mark",
occupation: "scientist",
age: 45,
present_working:false,
location: "texas"
},
{
_id: "bmasndvhjbcq",
name: "cooper",
occupation: "physicist",
age: 69,
location: "texas",
present_working:false
}
]
Remove the rows in records for which there is present_working:false. Data need not be removed in the database, it should be only modified in the aggregation pipeline
Expected output after removing only present_working:false and present_working:false should be kept in database. :
[
{
_id: "bmasndvhjbcw",
name: "lucas",
occupation: "scientist",
present_working:true,
age: 55,
location: "texas"
},
{
_id: "bmasndvhjbcx",
name: "mark",
occupation: "scientist",
age: 45,
location: "texas"
},
{
_id: "bmasndvhjbcq",
name: "cooper",
occupation: "physicist",
age: 69,
location: "texas"
}
]
MongoDB version: 4.0
You can use $$REMOVE as part of $project:
db.collection.aggregate([
{
$project: {
_id: 1,
name: 1,
occupation: 1,
age: 1,
location: 1,
present_working: { $cond: [ { $eq: [ "$present_working", false ] }, "$$REMOVE", "$present_working" ] }
}
}
])
Mongo Playground

Remove a particular field for all documents in a collection using MongoDB aggregation

How to Remove a particular value for all records in the collection using aggregation :
Have a collection with data :
[
{
_id: "bmasndvhjbcw",
name: "lucas",
occupation: "scientist",
present_working:true,
age: 55,
location: "texas",
date:2019-11-25T10:49:36.534+00:00
},
{
_id: "bmasndvhjbcx",
name: "mark",
occupation: "scientist",
age: 45,
present_working:true,
location: "texas",
date:null
},
{
_id: "bmasndvhjbcq",
name: "cooper",
occupation: "physicist",
age: 69,
location: "texas",
date:null
}
]
Remove the rows in records for which there is date:null. Data need not be removed in the database, it should be only modified in the aggregation pipeline
Expected output after removing only date:null :
[
{
_id: "bmasndvhjbcw",
name: "lucas",
occupation: "scientist",
present_working:true,
age: 55,
location: "texas",
date:2019-11-25T10:49:36.534+00:00
},
{
_id: "bmasndvhjbcx",
name: "mark",
occupation: "scientist",
age: 45,
present_working:true,
location: "texas"
},
{
_id: "bmasndvhjbcq",
name: "cooper",
occupation: "physicist",
age: 69,
location: "texas"
}
]
MongoDB version: 4.0
You can use $ifNull operator & $$REMOVE to do that :
db.collection.aggregate([
{
$addFields: {
date: {
$ifNull: [
"$date",
"$$REMOVE"
]
}
}
}
])
Test : MongoDB-Playground

MongoDB .Need to count fileds of an array

I have a collection like below
{ _id: 1, zipcode: "63109", students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 },
{ name: "jeff", school: 108, age: 15 }
] }
{ _id: 2, zipcode: "63110", students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
] }
{ _id: 3, zipcode: "63109", students: [
{ school: 100, age: 7 },
{ school: 100, age: 8 },
] }
{ _id: 4, zipcode: "63109", students: [
{ name: "barney", school: 102, age: 7 },
{ name: "ruth", school: 102, age: 16 },
] }
Note:Some document doesnot have name field.
I want to findout the count of name field.
Kindly suggest query to find count in mongo
You can do this with aggregation framework with $unwind. Let say your collection name is test:
db.test.aggregate(
{$unwind: '$students'},
{$match:{'students.name':{$exists:1}}},
{$group:{_id: '$students.name', count:{$sum:1}}},
{$project:{tmp:{name:'$_id', count:'$count'}}},
{$group:{_id:'Total Names', total:{$sum:1}, data:{$addToSet:'$tmp'}}}
)
Hope this is what you want!
You need to use the aggregation framework in this case.
The first aggregation step would be to use $unwind to turn the arrays into streams of documents.
Then you can use $group as a second aggregation step with $sum:1 to get the count of every name.
db.collection.aggregate([
{
$unwind: "$students"
},
{
$group: {
_id:"$students.name",
count: { $sum:1 }
}
}
]
This is doable through the aggregation framework
I'll assume your collection is called mycoll:
db.mycoll.aggregate([
{$unwind:'$students'},
{$group:{_id:'$name', 'count':{$sum:1}},
{$match:{'students.name':{$exists:1}}}
]);
References:
Aggregations http://docs.mongodb.org/manual/tutorial/aggregation-zip-code-data-set/
Exists: http://docs.mongodb.org/manual/reference/operator/query/exists/
Summing '1' essentially turns it into a count.

Mongodb : elemMatch

My problem cans be described as the following.
Give the following data (copied from mongo manual), how can i find the document which has zipcode 63109 and has 2 studends named "John", and "Jeff". I try
db.schools.find( { zipcode: 63109 },
{ students: { $elemMatch: { name : {"John", "Jeff"} } } } )
But it doesn't work. Could you help me, please ?
Thank you in advanced
{
_id: 1,
zipcode: 63109,
students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 },
{ name: "jeff", school: 108, age: 15 }
]
}
{
_id: 2,
zipcode: 63110,
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
]
}
{
_id: 3,
zipcode: 63109,
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
]
}
{
_id: 4,
zipcode: 63109,
students: [
{ name: "barney", school: 102, age: 7 },
]
}
I don't think it's possible to use $elemMatch here
The only solution I see is:
db.schools.find( { zipcode: 63109, $and: [{"students.name": "john"}, {"students.name": "jeff"}]} )