Remove embedded document in a nested array of documents - mongodb

My schema looks like this:
"content" : [
{
"_id" : ObjectId("4fc63de85b20fb72290000f8"),
"assets" : [
{
"path" : "temp/4f840af9565832fa14000002/4f840b1e565832fa14000007/4fc63de85b20fb72290000f7/content/I_Understanding_and_Measuring.pdf",
"_id" : ObjectId("4fc63def5b20fb722900010e")
},
{
"path" : "temp/4f840af9565832fa14000002/4f840b1e565832fa14000007/4fc63de85b20fb72290000f7/content/me.jpg",
"_id" : ObjectId("4fc63e4d5b20fb722900015d")
}
],
"content" : "",
"name" : "Downloads"
},
{
"_id" : ObjectId("4fc63dfd5b20fb722900012a"),
"assets" : [
{
"path" : "temp/4f840af9565832fa14000002/4f840b1e565832fa14000007/4fc63de85b20fb72290000f7/content/me.jpg",
"_id" : ObjectId("4fc63e055b20fb7229000147")
},
{
"path" : "temp/4f840af9565832fa14000002/4f840b1e565832fa14000007/4fc63de85b20fb72290000f7/content/thierry-henry-12-31-11-1.jpg",
"_id" : ObjectId("4fc63e525b20fb7229000164")
}
],
"content" : "",
"name" : "Bio"
}
],
I can retrieve this document with:
db.presentations.find({'content.assets._id': ObjectId('4fc63def5b20fb722900010e')})`
I've tried the following to remove an document from the assets collection with the line below, but to no avail:
db.presentations.update(
{'content.assets._id': ObjectId('4fc63def5b20fb722900010e')},
{$pull: {'content.assets': {'_id': ObjectId('4fc63def5b20fb722900010e')}}}
)
I'm trying to remove an item from the corresponding assets collection by its id. Any ideas?

You are so close! Remember that your outermost "content" is an array itself. So the following 2 character change works, use content.$.assets inside the value for $pull.
db.presentations.update(
{'content.assets._id': ObjectId('4fc63def5b20fb722900010e')},
{$pull: {'content.$.assets': {'_id': ObjectId('4fc63def5b20fb722900010e')}}}
)
Zoom ahead.

Related

MongoDB addToSet in nested array

I'm struggling to insert data inside a nested array in MongoDB.
My schema looks like this:
{
"_id" : ObjectId("5c0c55642440311ff0353846"),
"name" : "Test",
"email" : "test#gmail.com",
"username" : "test",
"password" : "$2a$10$RftzGtgM.DqIiaSvH4LqOO6RnLgQfLY3nk7UIAH4OAvvxo0ZMSaHu",
"created" : ISODate("2018-12-08T23:36:04.464Z"),
"classes" : [
{
"_id" : ObjectId("5c0c556e2440311ff0353847"),
"cName" : "1A",
"student" : [
{
"grades" : [ ],
"_id" : ObjectId("5c0c55812440311ff0353848"),
"name" : "StudentName",
"lname" : "StudenteLastName",
"gender" : "M"
}
insert }
],
"__v" : 0
}.
What I want to do is inserting a grade for the student inside "grades" array.
Expected result is:
{
"_id" : ObjectId("5c0c55642440311ff0353846"),
"name" : "Test",
"email" : "test#gmail.com",
"username" : "test",
"password" : "$2a$10$RftzGtgM.DqIiaSvH4LqOO6RnLgQfLY3nk7UIAH4OAvvxo0ZMSaHu",
"created" : ISODate("2018-12-08T23:36:04.464Z"),
"classes" : [
{
"_id" : ObjectId("5c0c556e2440311ff0353847"),
"cName" : "1A",
"student" : [
{
"grades" : [6],
"_id" : ObjectId("5c0c55812440311ff0353848"),
"name" : "StudentName",
"lname" : "StudenteLastName",
"gender" : "M"
}
]
}
],
"__v" : 0
}.
I tried some queries but none of them helped me, even searching a lot.
db.teachers.update({"_id": ObjectId("5c0c55642440311ff0353846"), "classes._id": ObjectId("5c0c556e2440311ff0353847"), "classes.student._id": ObjectId("5c0c55812440311ff0353848")},{$addToSet: {"classes.$.student.grades":6}})
Basically, I searched for the student with the first curly bracket (if I do "db.teachers.find(the three conditions) the result is correct) and then add to the grades array (of Integer) the value 6. But at this point I get errors, I think I'm making a mistake on the "adding" part.
I need also to do the same thing in Mongoose.
Any help is appreciated, thanks in advance!
Edit: I solved. I post my solution hoping it'll be useful to other:
For pushing inside a triple nested array do:
db.teachers.update({"_id":ObjectId("5c0c59985ae5981c58937e12"),"classes":{ $elemMatch : { _id : ObjectId("5c0c59a35ae5981c58937e13") }},"classes.student": { $elemMatch : { _id : ObjectId("5c0c59aa5ae5981c58937e14")} }},{$addToSet:{"classes.$.student.0.grades":3}})
https://docs.mongodb.com/manual/tutorial/query-array-of-documents/
Try using $elemMatch
"classes":{ $elemMatch : { _id : ObjectId("5c0c556e2440311ff0353847") }},
"classes.student": { $elemMatch : { _id : ObjectId("5c0c55812440311ff0353848")} }

How to filter a mongo document which contain some string in one of its properties?

I have a model users that contain some basic user information. I am just adding a search functionality for my app and i want to find users which contain the search term in their displayName property?
users model
[
{
"_id" : ObjectId("5bbda46a433ced65ac7c4699"),
"email" : "henoktes72#gmail.com",
"displayName" : "Henok Tesfaye",
"userId" : "5bbda46a433ced65ac7c4698",
"reputationNumber" : 0,
"questions" : [
"5bbf135d7883513e3839a34c"
],
"answers" : []
},
{
"_id" : ObjectId("5bbdb84a7da23035740bf056"),
"email" : "mezi#gmail.com",
"displayName" : "Mezi Villager",
"userId" : "5bbdb84a7da23035740bf055",
"reputationNumber" : 5,
"questions" : [
"5bbf1f137883513e3839a34f"
],
"answers" : [
"5bbf6933e564763770d81828"
]
}
]
If the search term is Henok the output must be
[
{
"_id" : ObjectId("5bbda46a433ced65ac7c4699"),
"email" : "henoktes72#gmail.com",
"displayName" : "Henok Tesfaye",
"userId" : "5bbda46a433ced65ac7c4698",
"reputationNumber" : 0,
"questions" : [
"5bbf135d7883513e3839a34c"
],
"answers" : []
}
]
.find({ displayName: "Henok" }) returns empty record.
You can use filter in loopback in where cond.
Two way to use regex in loopback.
Model.find({
where: {'displayName': /video/i }, //i for case-insensitive.
}, function(err, resilus) {
console.log(resilus);
});
OR
var search = new RegExp(search, 'i'); //i for case-insensitive.
Model.find({
where: {'displayName': search },
}, function(err, resilus) {
console.log(resilus);
});
Use can use regular expression in .find(...) function:
.find({displayName: /Henok/})

Embed root field in a subdocument within an aggregation pipeline

Maybe someone can help me with Mongo's Aggregation Pipeline. I am trying to put an object in another object but I'm new to Mongo and ist very difficult:
{
"_id" : ObjectId("5888a74f137ed66828367585"),
"name" : "Unis",
"tags" : [...],
"editable" : true,
"token" : "YfFzaoNvWPbvyUmSulXfMPq4a9QgGxN1ElIzAUmSJRX4cN7zCl",
"columns" : [...],
"description" : "...",
"sites" : {
"_id" : ObjectId("5888ae2f137ed668fb95a03d"),
"url" : "www.....de",
"column_values" : [
"University XXX",
"XXX",
"false"
],
"list_id" : ObjectId("5888a74f137ed66828367585")
},
"scan" : [
{
"_id" : ObjectId("5888b1074e2123c22ae7f4d3"),
"site_id" : ObjectId("5888ae2f137ed668fb95a03d"),
"scan_group_id" : ObjectId("5888a970a7f75fbd49052ed6"),
"date" : ISODate("2017-01-18T16:00:00Z"),
"score" : "B",
"https" : false,
"cookies" : 12
}
]
}
I want to put every object in the "scan"-array into "sites". So that it looks like this:
{
"_id" : ObjectId("5888a74f137ed66828367585"),
"name" : "Unis",
"tags" : [...],
"editable" : true,
"token" : "YfFzaoNvWPbvyUmSulXfMPq4a9QgGxN1ElIzAUmSJRX4cN7zCl",
"columns" : [...],
"description" : "...",
"sites" : {
"_id" : ObjectId("5888ae2f137ed668fb95a03d"),
"url" : "www.....de",
"column_values" : [
"University XXX",
"XXX",
"false"
],
"list_id" : ObjectId("5888a74f137ed66828367585"),
"scan" : [
{
"_id" : ObjectId("5888b1074e2123c22ae7f4d3"),
"site_id" : ObjectId("5888ae2f137ed668fb95a03d"),
"scan_group_id" : ObjectId("5888a970a7f75fbd49052ed6"),
"date" : ISODate("2017-01-18T16:00:00Z"),
"score" : "B",
"https" : false,
"cookies" : 12
}
]
}
}
Is there a step in the aggregation pipeline to perform this task?
With a single pipeline I don't see any other way but specifying each field individually as:
db.collection.aggregate([
{
"$project": {
"name": 1, "tags": 1,
"editable": 1,
"token": 1, "columns": 1,
"description": 1,
"sites._id": "$sites._id",
"sites.url": "$sites.url" ,
"sites.column_values": "$sites.column_values" ,
"sites.list_id": "$sites.list_id",
"sites.scan": "$scan"
}
}
])
With MongoDB 3.4 and newer, you can use the $addFields pipeline step instead of specifying all fields using $project. The advantage is that it adds new fields to documents and outputs documents that contain all existing fields from the input documents and the newly added fields:
db.collection.aggregate([
{
"$addFields": {
"sites._id": "$sites._id",
"sites.url": "$sites.url" ,
"sites.column_values": "$sites.column_values" ,
"sites.list_id": "$sites.list_id",
"sites.scan": "$scan"
}
}, { "$project": { "scan": 0 } }
])

how to match two fields in different lists in mongodb for update query

I need help please, I have to match two embedded document with their ids
for example my document structure is like this:
{
"id" : "00025",
"ean" : "01213134325",
"notify_stock" : NumberLong(10),
"specs" : [
{
"id" : "0005",
"spec" : [
{
"lang" : "fr-FR",
"text" : "taille"
}
],
"value" : [
{
"lang" : "fr-FR",
"text" : "grand"
}
]
}]
}
i have a file for multi language like this
sku_id;spec_id;spec_name;spec_value
00025;0005;size;big
00025;0006;color;black
so my query in mongodb is like this:
Modifier update query:
{
"skus.id" : "<string val>",
"skus.$.specs.id" : "<string val>"
}
Modifier update details:
{
"$push" : {
"skus.$.specs.$.spec" : {
"lang" : "<string val>",
"text" : "<string val>"
},
"skus.$.specs.$.value" : {
"lang" : "<string val>",
"text" : "<string val>"
}
}
}
when i execute this in Pentaho data integration with the step output mongodb, i got an error
"Too many positional (i.e. '$')
elements found in path 'skus.$.specs.$.spec'"

MongoDB update elements within array

I have a database of users like in the example below and I need to update the city of the user from Bonn to Berlin.
{
"_id" : "Louis",
"registered" : true,
"likes" : [
"tennis",
"cooking"
],
"addr" : {
"city" : "Bonn",
"country" : "Germany"
}
}
I have tried the following but it does not seem to work. Any ideas?
db.users.update( {_id:"Louis"}, {$set:{city:"Berlin"}} )
You should have quotes around field names in sub-documents
db.test.update( {_id : "Louis"}, {$set : {"addr.city" : "Berlin"}})