MongoDB - Returning only matching Array from Object - mongodb

i have the following document in a collection:
{
"_id" : 101,
"students" : [
{
"name" : "john",
"age" : 10,
"city":'CA'
},
{
"name" : "danial",
"age" : 15,
"city":'KA'
}
]
}
{
"_id" : 102,
"students" : [
{
"name" : "adam",
"age" : 20,
"city":'NY'
},
{
"name" : "johnson",
"age" : 12,
"city":'CA'
}
]
}
And i fire the following query:
db.data.find({'students.city':'CA'})
This returns me "students" objects from both the documents, as one instance matches the filter ("city"; 'CA') in both.
However, i desire to only get the matching array in the result. That is, i want the following result:
{
"_id" : 101,
"students" : [
{
"name" : "john",
"age" : 10,
"city":'CA'
}
]
}
{
"_id" : 102,
"students" : [
{
"name" : "johnson",
"age" : 12,
"city":'CA'
}
]
}
Please help.

You need to use $elemMatch in your projection:
> db.data.find({'students.city':'CA'},{ students:{ $elemMatch:{'city':'CA'} }})
{ "_id" : 101, "students" : [ { "name" : "john", "age" : 10, "city" : "CA" } ] }
{ "_id" : 102, "students" : [ { "name" : "johnson", "age" : 12, "city" : "CA" } ] }
Btw: I'd strongly suggest reading the Open letter to students with homework problems.

I think you should use an aggregation operation.
Here you have the documentation:
https://docs.mongodb.org/manual/aggregation/
And a similar question:
Retrieve only the queried element in an object array in MongoDB collection

Related

MongoDB $push operator and count characters in a name

I've populated a database in Mongodb with the following data in a collection named people.
{ "_id" : 0, "name" : "Bernice Pope", "age" : 69, "date" : "2017-10-04T18:35:44.011Z" }
{ "_id" : 1, "name" : "Eric Malone", "age" : 57, "date" : "2017-10-04T18:35:44.014Z" }
{ "_id" : 2, "name" : "Blanche Miller", "age" : 35, "date" : "2017-10-4T18:35:44.015Z" }
{ "_id" : 3, "name" : "Sue Perez", "age" : 64, "date" : "2017-10-04T18:35:44.016Z" }
{ "_id" : 4, "name" : "Ryan White", "age" : 39, "date" : "2017-10-04T18:35:44.019Z"}
{ "_id" : 5, "name" : "Grace Payne", "age" : 56, "date" : "2017-10-04T18:35:44.020Z" }
{ "_id" : 6, "name" : "Jessie Yates", "age" : 53, "date" : "2017-10-04T18:35:44.020Z"}
{ "_id" : 7, "name" : "Herbert Mason", "age" : 37, "date" : "2017-10-4T18:35:44.020Z" }
{ "_id" : 8, "name" : "Jesse Jordan", "age" : 47, "date" : "2017-10-04T18:35:44.020Z"}
{ "_id" : 9, "name" : "Hulda Fuller", "age" : 25, "date" : "2017-10-04T18:35:44.020Z"}
Based on the people collection, I need to create a view named PeopleNames which likes below:
{ "LengthOfName": 8, "names" : [ "Sue Perez" ]}
{ "LengthOfName" : 9, "names" : [ "Ryan White" ]}
{ "LengthOfName" : 10, "names" : [ "Eric Malone", "Grace Payne" ]}
{ "LengthOfName" : 11, "names" : [ "Bernice Pope", "Jessie Yates", "Jesse Jordan", "Hulda Fuller" ]}
{ "LengthOfName" : 12, "names" : [ "Herbert Mason" ]}
{ "LengthOfName" : 13, "names" : [ "Blanche Miller"]}
LengthOfName is the total number of the characters in the last name and first name.
My approach is to first add the names into an array, the use $split operator to split the names and use $strLenCP to count the characters.
db.people.aggregate([
{
$project : {
name : 1,
name_array : [{$push : { $split : {$name : " "}}}]
}
}
,{
$unwind : "$name_array"
},{
$project : {
name : 1,
nameLength : {$strLenCP : $name_array}
}
},{
$group :{
_id : "$nameLength",
nameLength: 1
}
}])
But I am receiving error saying that my "$name_array" is undefined Any ideas?
The $push aggregation operator is only available in the $group stage.
You can group the documents by the name length (after trimming the spaces in the name using $replaceAll) and use $push to add the names to the names array. You can then add a $project stage to add the LengthOfName field to the documents and finally add a $sort stage to sort the documents by the LengthOfName field.
db.collection.aggregate([
{
$group: {
_id: {
$strLenCP: {
$replaceAll: {
input: "$name",
find: " ",
replacement: ""
}
}
},
names: {
$push: "$name"
}
}
},
{
$project: {
_id: 0,
LengthOfName: "$_id",
names: "$names",
}
},
{
$sort: {
LengthOfName: 1,
}
}
])
MongoPlayground

How to update array element in mongodb document?

This query is updating successfully:
db.product.updateMany({"Rno":{$in:["111","222","333"]}},{$set:{"subjwmarks.maths":99}});
Before updating:
{
"_id" : ObjectId("5a572886964d881dab9f1f55"),
"Rno" : "111",
"stuname" : "sravan",
"subjwmarks" : [
{
"maths" : 88.0,
"english" : 99.0,
"Clang" : 97.0
}
],
"total" : 284.0,
"grade" : "A",
"organization" : "Tata"
};
After updating the query returns this value:
{
"_id" : ObjectId("5a572886964d881dab9f1f55"),
"Rno" : "111",
"stuname" : "sravan",
"subjwmarks" : [
{
"maths" : 99,
}
],
"total" : 284.0,
"grade" : "A",
"organization" : "Tata"
};
Value should be:
{
"_id" : ObjectId("5a572886964d881dab9f1f55"),
"Rno" : "111",
"stuname" : "sravan",
"subjwmarks" : [
{
"maths" : 99,
"english" : 99.0,
"Clang" : 97.0
}
],
"total" : 284.0,
"grade" : "A",
"organization" : "Tata"
}
But other elements of that array were deleted.
Can anyone suggest how to fix this problem?
db.product.updateMany({"Rno":{$in:["111","222","333"]}, subjwmarks:{ $exists: true}},{$set:{"subjwmarks.$.maths":100}});
https://docs.mongodb.com/manual/reference/operator/update/positional/
Note: subjwmarks must be in query part

How to query an array of _id in MongoDB?

I have collection Collection1 and I need to fetch an array like: [id1, id2, id3, ...] (array which consist of _id`s for every element in this collection). Is there any way to do this query with MongoDB tools ? Thank you!
You will have to use cursor.toArray() function on result of find having a projection document projecting only _id i.e ObjectId() value
MongoDB Enterprise > db.users.find().pretty()
{
"_id" : ObjectId("570e1d465a44f125ef156791"),
"name" : "Ritesh Talreja",
"age" : 22,
"gender" : "M"
}
{
"_id" : ObjectId("570e1e1d5a44f125ef156792"),
"name" : "Saloni",
"age" : 21,
"gender" : "F"
}
{
"_id" : ObjectId("570e1e485a44f125ef156793"),
"name" : "abcd",
"age" : 22,
"gender" : "M"
}
{
"_id" : ObjectId("570e28d45a44f125ef156794"),
"name" : "Saloni",
"age" : 21,
"gender" : "F"
}
{ "_id" : 123 }
MongoDB Enterprise > db.users.find({}, {_id:1}).toArray()
[
{
"_id" : ObjectId("570e1d465a44f125ef156791")
},
{
"_id" : ObjectId("570e1e1d5a44f125ef156792")
},
{
"_id" : ObjectId("570e1e485a44f125ef156793")
},
{
"_id" : ObjectId("570e28d45a44f125ef156794")
},
{
"_id" : 123
}
]
MongoDB Enterprise >
As an addition you can also use:
MongoDB Enterprise > db.users.distinct("_id")
[
123,
ObjectId("570e1d465a44f125ef156791"),
ObjectId("570e1e1d5a44f125ef156792"),
ObjectId("570e1e485a44f125ef156793"),
ObjectId("570e28d45a44f125ef156794")
]
MongoDB Enterprise >

Select all distinct subdocuments

I am have the next document collection:
{ "_id" : ObjectId("568dc77473bf57f465da61dd"), "name" : "Rama", "items" : [ { "id" : 40, "name" : "Botella" }, { "id" : 30, "name" : "Frasco" } ] }
{ "_id" : ObjectId("568dc78873bf57f465da61de"), "name" : "Pepe", "items" : [ { "id" : 40, "name" : "Botella" }, { "id" : 29, "name" : "Cigarrillo" } ] }
Each document have a collection of items. Each item is a document. So i have the list of all distinct items on the collection:
{ "id" : 40, "name" : "Botella" },
{ "id" : 29, "name" : "Cigarrillo" },
{ "id" : 30, "name" : "Frasco" }
With $unwind i obtained one item per document:
db.test.aggregate([{'$unwind': '$items'}, {'$project': {'items.id': 1, 'items.name': 1, '_id': 0}}])
{ "items" : { "id" : 40, "name" : "Botella" } }
{ "items" : { "id" : 30, "name" : "Frasco" } }
{ "items" : { "id" : 40, "name" : "Botella" } }
{ "items" : { "id" : 29, "name" : "Cigarrillo" } }
But now, i don't know how get the distinct 'items'. I am doing my first steps with MongoDB.
Any ideas ?
You can group on the items.id and items.name to get the distinct items
db.test.aggregate([
{'$unwind': '$items'},
{'$group': {'_id':{'id':'$items.id', 'name':'$items.name'}}},
{'$project': {'items': '$_id', '_id':0}}])

Deleting a single object from an array of objects in MongoDB

Say we have the following collection of documents:
{ "_id" : ObjectId("50a69fa904c8310609600be3"), "id" : 100, "city" : "San Francisco", "friends" : [ { "id" : 1, "name" : "John" }, { "id" : 2, "name" : "Betty" }, { "id" : 3, "name" : "Harry" } ] }
{ "_id" : ObjectId("50a69fc104c8310609600be4"), "id" : 200, "city" : "Palo Alto", "friends" : [ { "id" : 1, "name" : "Carol" }, { "id" : 2, "name" : "Frank" }, { "id" : 3, "name" : "Norman" } ] }
{ "_id" : ObjectId("50a69fc304c8310609600be5"), "id" : 300, "city" : "Los Angeles", "friends" : [ { "id" : 1, "name" : "Fred" }, { "id" : 2, "name" : "Neal" }, { "id" : 3, "name" : "David" } ] }
.
.
.
Now let's say that Frank (Palo Alto, id=2) is no longer my friend, and I want to delete him from the collection. I thought the following might work, but it doesn't:
db.test.update({"city":"Palo Alto"},{"$pull":{"friends.name":"Frank"}})
I'd like to be able to do something like that. Delete an object within an array within a collection of documents. How do you do this?
You were close. The query should be like this:
db.test.update({"city":"Palo Alto"},{"$pull":{"friends":{"name":"Frank"}}});
$pull takes an object whose field specifies the field array "friends". The value {"name":"Frank"} represents the query (to run inside the array) to find the element to pull out.