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")} }
Related
I'm learning MongoDB on my own. I have a collection with entries that look like this:
{
"_id" : ObjectId("5d0c13fbfdca455311248d6f"),
"borough" : "Brooklyn",
"grades" :
[
{ "date" : ISODate("2014-04-16T00:00:00Z"), "grade" : "A", "score" : 5 },
{ "date" : ISODate("2013-04-23T00:00:00Z"), "grade" : "B", "score" : 2 },
{ "date" : ISODate("2012-04-24T00:00:00Z"), "grade" : "A", "score" : 5 }
],
"name" : "C & C Catering Service",
"restaurant_id" : "40357437"
}
And I want to find all restaurants in Brooklyn with at least one grades.grade of A.
I've figured out the first half of the puzzle:
db.restaurants.find({borough:{$eq:"Brooklyn"}})
But how do I query in the "grades" array for grade A?
Use dot (.) to access and query nested objects:
db.restaurants.find({'borough':{$eq:"Brooklyn"}, 'grades.grade': 'A'})
db.restaurants.find({"borough" : "Brooklyn","grades.grade":"A"})
How do i remove array item from collection in mongodb? Below is my structure.
{
"__v" : 12,
"_id" : ObjectId("52cc27daasdsc797ec7s8000001"),
"email" : "email#email.com",
"joindate" : ISODate("2014-01-07T16:14:18.158Z"),
"location" : "Canada",
"name" : "Albert",
"oauthID" : 58558855,
"myvideos" : [
{
"vid" : "wssEoGquzsiw1c",
"date" : ISODate("2014-06-01T05:28:32.713Z")
},
{
"vid" : "0_Vko7RXsdsmoI",
"date" : ISODate("2014-06-01T05:29:01.888Z")
},
{
"vid" : "ctbvhucsds050g",
"date" : ISODate("2014-06-01T05:29:27.395Z")
}
],
"username" : "myusername"
}
I would like to remove item vid (ctbvhucsds050g) from the myvideos array.
Appreciate any advice.
Found a solution to this.
db.users.update({"name":"Albert"}, {'$pull': {"myvideos": {"vid": "ctbvhucsds050g" }}});
I must be overlooking really simple, here's a sample of my db :
{ "_id" : ObjectId("545e7e45a69b6c5c0caeafcc"), "url" : "http://example.com/id=4314936", "name" : "product1", "retailer" : "123", "extra" : [ ], "timestamp" : 1415478797263, "processed" : 0 }
{ "_id" : ObjectId("545e7e45a69b6c5c0caeafcc"), "url" : "http://example.com/id=4314936", "name" : "product2", "retailer" : "123", "extra" : [ ], "timestamp" : 1415478797263, "processed" : 0 }
{ "_id" : ObjectId("545e7e45a69b6c5c0caeafcc"), "url" : "http://example.com/id=4314936", "name" : "product3", "retailer" : "123", "extra" : [ ], "timestamp" : 1415478797263, "processed" : 0 }
{ "_id" : ObjectId("545e7e45a69b6c5c0caeafcc"), "url" : "http://example.com/id=4314936", "name" : "product3", "retailer" : "123", "extra" : [ ], "timestamp" : 1415478797263, "processed" : 0 }
I'm trying to get 2 results only using :
db.products.find({timestamp:1415478797263,processed:0},{},{limit:2})
I have read and tried similar questions on Stack Overflow, so please keep that in mind before flagging as duplicate.
No matter what I try it gives me the full set... The strangest thing is that I'm using a similar find() elsewhere and it works. An experienced pair of eyes should be able to spot the problem, thanks in advance!!
use this query, does it work?
db.products.find({timestamp:1415478797263,processed:0}).limit(2)
now to use it with node js native driver you can do this
db.products.find({timestamp:1415478797263,processed:0}).limit(2).each(function(err, doc) {
console.dir(doc);
});
or in array form you can get this as
db.products.find({timestamp:1415478797263,processed:0}).limit(2).toArray(function(err, docs) {
console.log("Returned #" + docs.length + " documents");
})
I'm kind of stuck with the following problem. I have a MongoDB filled with documents, of these documents (I have a list with Id's) I need to insert a field.
I have this document:
{
"id" : 3639,
"type" : "P",
"createdate" : "2011-10-19T11:45:14+0200",
"name_creator" : "",
"latitude" : "50.887",
"longitude" : "9.14999",
"themes" : [{
"name" : "Fun",
"id" : "4"
}, {
"name" : "Kids",
"id" : "5"
}]
}
I need a query the can insert the themes field into the document, the current themes field does not have to be updates, just 1 new one. I have over 300 Id's where this has to be done.
The document should then look like this:
(all the other fields in themes should be removed, just one new one 'Outside')
{
"id" : 3639,
"type" : "P",
"createdate" : "2011-10-19T11:45:14+0200",
"name_creator" : "",
"latitude" : "50.887",
"longitude" : "9.14999",
"themes" : [{
"name" : "Outside",
"id" : "6"
}]
}
I would normally write a bit of Java code that would loop over the documents and change them, but I believe (hope) this could be done in a query.
Anyone got an idea on how I could do this?
Thanks for any help!
All you need to do is
db.collection.update(
{id : {$in : [your list of ids]}},
{$set : {
theme : [{
"name" : "Outside",
"id" : "6"
}]
}},
{multi : true}
)
I'm playing around with mongoDB and I can't figure out what is the difference between my two queries.
I use following collection:
{
"_id" : ObjectId("520b79869971eb1a0fdd0ad4"),
"created" : 1376483718636,
"updated" : 1376483718636,
"firstName" : "Jakob",
"lastName" : "D",
"email" : "jakob.d#test.com",
"emailValidated" : false,
"phoneNumber" : "",
"lastLogin" : 1376483718624,
"linkedProviders" : [
{
"userId" : "1XXXXXXXX6",
"providerId" : "facebook",
"password" : "",
"salt" : "",
"authMethod" : "oauth2",
"avatarUrl" : ""
}
],
"userRoles" : [
"ADMIN"
]
},
{
"_id" : ObjectId("520b7dd09971ebcd35dd0ad6"),
"created" : 1376484816666,
"updated" : 1376484816666,
"firstName" : "Jakob",
"lastName" : "D",
"email" : "jakob.d#test.com",
"emailValidated" : false,
"phoneNumber" : "",
"lastLogin" : 1376484816666,
"linkedProviders" : [
{
"userId" : "jakob.d#test.com",
"providerId" : "userpass",
"password" : "7e4aff9e0d90db2318ffcc689c11b66d",
"salt" : "N1GgNvy3NnS0i5GFDyglQZ9s4CeFNndn",
"authMethod" : "userPassword",
"avatarUrl" : ""
}
],
"userRoles" : [
"ADMIN"
]
}
The two queries that gives me the correct and same result(the one with objectId 520b79869971eb1a0fdd0ad4) are:
db.users.find({"linkedProviders.userId":"1XXXXXXXX6","linkedProviders.providerId":"facebook"})
db.users.find({"linkedProviders": {"$elemMatch": {"userId":"1XXXXXXXX6" },"$elemMatch": {"providerId":"facebook" }}})
So what is the difference between these two?
The difference is that $elemMatch finds items for one single array element.
This solution:
db.users.find({
"linkedProviders.userId": "1XXXXXXXX6",
"linkedProviders.providerId": "facebook"
})
Finds any user that has that userId and that providerId, but possibly in different items in linkedProviders, e.g., if linkedProviders[0].userId matches the first and linkedProviders[1].providerId matches the second part of the query, the full document (i.e., the user) will match that query.
On the other hand,
db.users.find({
"linkedProviders": {
"$elemMatch": {
"userId": "1XXXXXXXX6",
"providerId": "facebook"
}
}
})
will match only if the index values (0 and 1 in the previous example) are the same in the document, i.e., only if one array element matches both.
When there's only one key-value mapping in the $elemMatch, it should do the same as the query with the key-value mapping applied directly.
More information:
http://docs.mongodb.org/manual/reference/operator/elemMatch/#op._S_elemMatch