How to use Mongo $pop? - mongodb

I am able to $push an object onto a Mongo array as follows:
db.foo.update({},{$push:{bar:3}})
But I can't find a syntax that will allow me to $pop the last item from the list.
I've tried things like:
db.foo.find({$pop:{bar:1}})
which does nothing. I've also tried
db.foo.find({id:23},{$pop:{bar:1}})
which outputs:
error: { "$err" : "Unsupported projection option: bar", "code" : 13097 }
Any ideas?

$pop exists and works almost like you've got it there, but you need to find some elements first!
db.foo.update({ _id: someId }, { $pop: { bar:1 } });
See the docs.

Related

How to change attribute name of the embed type?

How I can change the name of the embed type by query $rename?
{ list_name: [{ name_1: String }] } => { list_name: [{ name_2: String }] }
I tried db.getCollection('test').updateMany({}, { $rename: { 'list_name.name_1': 'name_2' }})
But it's throwing an error: WriteError: cannot use the part (list_name of list_name.name_1) to traverse the element ({list_name: [ { name_1: "test" } ]})
$rename does not work if these fields are in array elements
Refer
To achieve, you need $unset and $set document by document. You can use bulkwrite also.
list_name is an array. Hence $rename didn't work.
When I search, I get this. You can refer the second answer if you have less number of docs.
Else, you need to use either bulk write or mongo dump options.

How do you populate a field if it doesn't exist in Mongo?

I am writing an aggregate for MongoDB, but am running into an issue with making sure a field is always present inside of my $project query. I would like to write something like this:
{
'foo': '$foo.bar' || ''
}
Which would populate foo with foo.bar or an empty string if the property is not there. I've tried using $or, $cond, and $exists, but none of them are guaranteeing the presence of foo.
Figured it out:
{
'foo': {
$cond: {
'if': "$foo.bar",
'then': "$foo.bar",
'else': ""
}
}
}
In my opinion, $exists operator is best way to check some filed is exists or not:
db.collection.find({ 'somefiled' : { '$exists' : true }});
You will not get anything when a field does not exist.

Mongo DB find() query error

I am new to MongoDB. I have a collection called person. I'm trying to get all the records without an _id field with this query:
db.person.find({}{_id:0})
but the error is
syntax error: unexpected {
but if i write
db.person.find()
it works perfectly.
Consider following documents inserted in person collection as
db.person.insert({"name":"abc"})
db.person.insert({"name":"xyz"}
If you want to find exact matching then use query as
db.person.find({"name":"abc"})
this return only matched name documents
If you want all names without _id then use projeciton id query as
db.person.find({},{"_id":0})
which return
{ "name" : "abc" }
{ "name" : "xyz" }
According to Mongodb manual you have little wrong syntax, you forgot to give comma after {}
Try this :
db.person.find({}, { _id: 0 } )

How many level can mongodb append sub-documents dynamicaly?

It seems that i can go further than one subdocument if i want to add it dynamicaly, here is the code:
db.users.update({"pup.cmn.id":id}, {"$addToSet":{"pup.cmn":{"abus":email}}})
this give error:
OperationFailure: can't append to array using string field name: cmn
then, if i add positional element i get this:
db.users.update({"pup.cmn.id":id}, {"$addToSet":{"pup.$.cmn":{"abus":email}}})
"cmn" :
[
{
"fto" : ObjectId("5190e8a53a5f3a0c102af045")
"id" : "14.05.2013 12:29:53"
},
{
"abus" : "u...#example.com"
}
]
so as you can see, it will add it in the same level, and i dont want that, because the application will get errors.
It seems that Mongodb for the time of writing (2.4.x) have not this feature, there is a ticket:
https://jira.mongodb.org/browse/SERVER-831

Add new field to all documents in a nested array

I have a database of person documents. Each has a field named photos, which is an array of photo documents. I would like to add a new 'reviewed' flag to each of the photo documents and initialize it to false.
This is the query I am trying to use:
db.person.update({ "_id" : { $exists : true } }, {$set : {photos.reviewed : false} }, false, true)
However I get the following error:
SyntaxError: missing : after property id (shell):1
Is this possible, and if so, what am I doing wrong in my update?
Here is a full example of the 'person' document:
{
"_class" : "com.foo.Person",
"_id" : "2894",
"name" : "Pixel Spacebag",
"photos" : [
{
"_id" : null,
"thumbUrl" : "http://site.com/a_s.jpg",
"fullUrl" : "http://site.com/a.jpg"
},
{
"_id" : null,
"thumbUrl" : "http://site.com/b_s.jpg",
"fullUrl" : "http://site.com/b.jpg"
}]
}
Bonus karma for anyone who can tell me a cleaner why to update "all documents" without using the query { "_id" : { $exists : true } }
For those who are still looking for the answer it is possible with MongoDB 3.6 with the all positional operator $[] see the docs:
db.getCollection('person').update(
{},
{ $set: { "photos.$[].reviewed" : false } },
{ multi: true}
)
Is this possible, and if so, what am I doing wrong in my update?
No. In general MongoDB is only good at doing updates on top-level objects.
The exception here is the $ positional operator. From the docs: Use this to find an array member and then manipulate it.
However, in your case you want to modify all members in an array. So that is not what you need.
Bonus karma for anyone who can tell me a cleaner why to update "all documents"
Try db.coll.update(query, update, false, true), this will issue a "multi" update. That last true is what makes it a multi.
Is this possible,
You have two options here:
Write a for loop to perform the update. It will basically be a nested for loop, one to loop through the data, the other to loop through the sub-array. If you have a lot of data, you will want to write this is your driver of choice (and possibly multi-thread it).
Write your code to handle reviewed as nullable. Write the data such that if it comes across a photo with reviewed undefined then it must be false. Then you can set the field appropriately and commit it back to the DB.
Method #2 is something you should get used to. As your data grows and you add fields, it becomes difficult to "back-port" all of the old data. This is similar to the problem of issuing a schema change in SQL when you have 1B items in the DB.
Instead just make your code resistant against the null and learn to treat it as a default.
Again though, this is still not the solution you seek.
You can do this
(null, {$set : {"photos.reviewed" : false} }, false, true)
The first parameter is null : no specification = any item in the collection.
"photos.reviewed" should be declared as string to update subfield.
You can do like this:
db.person.update({}, $set:{name.surname:null}, false, true);
Old topic now, but this just worked fine with Mongo 3.0.6:
db.users.update({ _id: ObjectId("55e8969119cee85d216211fb") },
{ $set: {"settings.pieces": "merida"} })
In my case user entity looks like
{ _id: 32, name: "foo", ..., settings: { ..., pieces: "merida", ...} }