How to insert a translation into a subdocument nested in an array? - mongodb

With a schema like this, where the "items" field contains an array of subdocuments with nested translations :
{
"_id" : ObjectId("513740415b51ea0803000001"),
"items" : [
{
"id" : ObjectId("5137407f5b51ea100f000000"),
"title" : {
"en" : "Yes",
"fr" : "Oui",
"es" : "Si"
}
},
{
"id" : ObjectId("5137407f5b51ea100f000003"),
"title" : {
"en" : "No"
}
}
],
}
How would you add a translation to a specific item id ?

You can use the $ positional operator to update a specific array element of a doc.
For example, to add "de": "nein":
db.test.update(
{'items.id': ObjectId("5137407f5b51ea100f000003")},
{$set: {'items.$.title.de': 'nein'}})
The $ in the $set object represents the index of the element in items that the query selection parameter matched.

You can do it like that:
db.yourColName.update({"items.id" : "itemId"}, {$set : {"translationField" : "translationValue"}})
Over here in the first part of the query you are searching for the direct item in the array and set a new field + value for it.
The thing is, like you have already noticed, that Mongo doesn't have static schema. So $set will either update already existing field or create a new one. It all depends on the field name you set in the subquery.
To get to the direct document use the $ operator: items.$.title.fr where $ would represent the current object.

Related

Using MongoDB field as key reference for another value

I'm still new to MongoDB, in an aggregate query I'm trying to use a value from a field as the key to getting the other value. For example in the following document,
{
"_id" : ObjectId("5d9c245bb6c0ac7a34a43bf5"),
"status" : {
"code" : "ES004",
"params" : {
"star" : "VSP"
}
},
"description" : "{star} has been added to the cast/crew officially",
"stringToReplace" : "{star}",
"valueToReplace" : "status.params.star"
}
I wanted to replace the value of stringToReplace in description with the value of valueToReplace (i.e., value in status.params.star which is VSP)
Is there any way of doing this in an aggregate query or only way to go with this is Mongo shell?

Using $set to update a document's value with key containing a dot(.), MongoDB

I have this very basic collection (blog.posts) from which I want to update the value of a key (author.name) using the $set modifier. Here is a sample of a document from the collection:
{
"_id" : ObjectId("5ca66e7d8a3bb6e58e0d85f4"),
"s_id": "unique_post",
"title" : "MongoDB is cool",
"author.name" : "Terence"
}
I want to change the value of the author.name key from Terence to Benjamin and this is the query with which I'm trying to acheive the result:
db.blog.posts.update({"s_id": "unique_post"}, {"$set":{"author.name":"Benjamin"}})
The issue is that when I execute this query, I end up with a new nested ducument as shown:
{
"_id" : ObjectId("5ca66e7d8a3bb6e58e0d85f4"),
"title" : "MongoDB is cool",
"author.name" : "Terence",
"author" : {
"name" : "Benjamin"
}
}
I know that this is to be expected but my question is: How do I modify a value in a document who's key contains a dot(.) ?
Please I'm new to mongoDB and any other tips would be highly appreciated.
As per MongoDB documentation dot(.) is a restricted character in field names. So you cannot have dot(.) in field names. That is the reason it converts the dot(.) value into subdocument.

removing object from nested array of objects mongodb

I've got collection with volunteer information in it, and it lists the volunteers as an array of objects. I can display all the shifts for each volunteer, but removing one from the array is proving difficult for me:
Sample data:
"_id" : ObjectId("59180305c19dbaa4ecd9ee59"),
"where" : "Merchandise tent",
"description" : "Sell gear at the merchandise tent.",
"shifts" : [
{
"dateNeeded" : ISODate("2017-06-23T00:00:00Z"),
"timeslot" : "8:00 - NOON",
"needed" : 2,
"_id" : ObjectId("591807546a71c3a57d1a2105"),
"volunteers" : [
{
"fullname" : "Mary Mack",
"phone" : "1234567890",
"email" : "mary#gmail.com",
"_id" : ObjectId("591ce45bc7e8a8c7b742474c")
}
]
},
The data I have available for this is:
_id, where, shifts.timeslot, shifts.dateNeeded, volunteers.email
Can someone help me? Lets say Mary Mack wants to unVolunteer for the 8 - Noon shift at the merchandise tent. She may be listed under other shifts as well, but we only want to remove her from this shift.
You can do this by specifying something to match the "document" and then the required "shifts" array entry as the query expression for an .update(). Then apply the positional $ operator for the matched array index with $pull:
db.collection.update(
{ "_id": ObjectId("59180305c19dbaa4ecd9ee59"), "shifts.timeslot": "8:00 - NOON" },
{ "$pull": { "shifts.$.volunteers": { "fullname": "Mary Mack" } } }
)
That is okay in this instance since you are only trying to "match" on the "outer" array in the nested structure and the $pull has query arguments of it's own to identify the array entry to remove.
You really should be careful using "nested arrays" though. As whilst a $pull operation like this works, updates to the "inner" array are not really possible since the positional $ operator will only match the "first" element that meets the condition. So your example of "Mary Mack" in multiple shifts would only ever match in the first "shifts" array entry found.
Try this
db.example.update(
{},
{ $unset: {"Mary Mack":1}},
false, true
)

Meteor/Mongo nested arrays update

I'm new to meteor/mongo/js as a stack and I'm getting lost in JSON arrays and referencing them. Based another SO answer ( and the docs) I think I am close...
A document in the Orders collection, the document has nested arrays.
Order -> orderLines -> lineItems:
Sample doc:
{
"_id" : "27tGpRtMWYqPpFkDN",
"orderLines" : [
{
"lineId" : 1,
"name" : "Cheese & Pickle",
"instructions" : "",
"lineItems" : [
{
"name" : "Cheddar Cheese",
"quantity" : 1
},
{
"name" : "Branston Pickle",
"quantity" : 1
},
{
"name" : "Focaccia Roll",
"quantity" : 1
}
]
}
]
}
What I'm trying to do from the meteor/mongo shell:
Add "instructions" of "foo" to orderLines where lineId = 1
Put a new item on lineItems array
This appears to hang...
meteor:PRIMARY> db.orders.update({_id:"27tGpRtMWYqPpFkDN","orderLines.lineId":"1", {$set: {"orderLines.$.instructions":"foo"}})
...
This doesn't like the identifier in the query
meteor:PRIMARY> db.orders.update({_id:"27tGpRtMWYqPpFkDN", "orderLines.lineId":"1"}, {$push:{"orderLines.$.lineItems":" { "name" : "butter", "quantity" : 1}"}});
2015-10-27T16:09:54.489+0100 SyntaxError: Unexpected identifier
Thanks all for your comments... but I found out some answers, posted for reference
Item 1 - using $set on a value within an array
This was failing due to two typos, one missing closing } at the end of the query, second was quoting the value "1" for itemId in the query.
This works:
db.orders.update({_id:"27tGpRtMWYqPpFkDN", orderLines.lineId":1},
{$set: {"orderLines.$.instructions":"foo"}})
I also realised that when I said "It appears to hang" it is the cli waiting for a valid statement, so hints at a missing } or )!
Item 2 - using $push to add data to an array - 2 levels nested
This was failing due to quoting around the array data
db.orders.update({_id:"27tGpRtMWYqPpFkDN", "orderLines.lineId":1 },
{$push:{"orderLines.$.lineItems": { "name" : "butter", "quantity" : 1} }})
Nested Arrays: can use $ positional operator
What I want to do next is use $set on an item in the second level array, and this would require using the $ positional operator twice:
db.orders.update({"orderLines.lineId":1, lineItems.name:"Cheddar Cheese"},
{$set: {"orderLines.$.lineItems.$.quantity": 2}})
This throws an error:
Too many positional (i.e. '$') elements found in path
There is an open MongoDB enhancement request for this but it's been open since 2010
$push adds a new element to an array. You're merely trying to set the value of a particular key in an array element.
Try:
db.orders.update({ _id: "27tGpRtMWYqPpFkDN", "orderLines.lineId": 1},
{ $set: { "orderlines.$.instructions": "foo" }})
docs

Filter list of embedded documents with reference field

I'm pretty new to MongoDB and I'm experiencing it with mongoengine.
Given this 'User' model where 'bets' is an embedded document list which each element contains a reference to a 'match' document,
{
"_id" : ObjectId("53df77cef4c9610f28cbff14"),
"name" : "Test",
"admin" : false,
"bets" : [
{ "match" : ObjectId("53e1511df4c9610bf52f5b7a"), "expectedResult" : "1" }
]
}
how can I get 'bets' elements, passed to query the matchId?
I tried to do
User.objects.filter(bets__match={'match._id':match.id})
where 'match' is the object I need to filter by but I get an empty array.