Query ReactiveMongo by a nested field - mongodb

I have an object in a collection:
{ "id" : "123", "option" : { "key" : "one" , "value" : "1" }}
I can find the object like this:
collection.find(BSONDocument("option" -> BSONDocument("key" -> "one", "value" -> "1")))
However, what I need is to be able to find the object only by the value ('1' in the example), without having to specify the whole child document.
Is there any way to do it in Reactivemongo?

To query by fields in an embedded or a nested document, use dot notation:
collection.find(BSONDocument("option.value" -> "1"))

Related

Update or Insert object list into mongodb array in one query

I am trying to upsert array elements for a single document.
I want to provide list of objects to mongo query, and for each object if exists (based on some field) in an mongo document array, replace the object in the array, if not exists, add it to the array.
I know this can be done using application side, but can this be done using 1 transactional query?
example:
{
"_id" : ObjectId("50b429ba0e27b508d854483e"),
"array" : [
{
"id" : "1",
"letter" : "a"
},
{
"id" : "2",
"letter" : "b"
},
{
"id" : "3",
"letter" : "c"
}
],
"tester" : "tom"
}
Now, I want to pass to pass to my query the following objects:
{
"id" : "3",
"letter" : "c-new"
"newField": "some string"
},
{
"id" : "4",
"letter" : "D"
}
Based on id field I want mongo to see that:
id:3 already exists, so it will replace the current element with the new object provided
id:4 doesn't exists, so it will add it to the array elements.
(that's basically called upsert).

updating mongo documents based in map value and remove that value

am currently working in Go and have a mongo database (connected via gopkg.in/mgo.v2) so, right now I have a data structure similar to:
{
"_id" : "some_id_bson",
"field1" : "value1",
"field2" : {
{
"key1" : "v1",
"key2" : "v2",
"key3" : "v3",
"key4" : "v4"
}
}
}
So, basically what I need to do (as an example) is to update in the database all the records that contains key1 and remove that from the json, so the result would be something like:
{
"_id" : "some_id_bson",
"field1" : "value1",
"field2" : {
{
"key2" : "v2",
"key3" : "v3",
"key4" : "v4"
}
}
}
What can I use to achieve this? I have been searching and cannot find something oriented to maps (field2 is a map). Thanks in advance
It seems like you're asking how to remove a property from a nested object in a particular document, which appears as if to be answered here: How to remove property of nested object from MongoDB document?.
from the main answer there:
Use $unset as below :
db.collectionName.update({},{"$unset":{"values.727920":""}}) EDIT For
updating multiple documents use update options like :
db.collectionName.update({},{"$unset":{"values.727920":""}},{"multi":true})
Try using $exists and $unset:
query:= bson.M{"$exists":bson.M{"field2.key1":true}}
replace:=bson.M{"$unset":bson.M{"field2.key1":""}}
collection.UpdateAll(query,replace)
This should find all documents containing field2.key1, and remove that.

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?

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

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

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.