Compacting mongodb queries - mongodb

With the mongo shell, I am doing something in a way which I think should be simpler. I make a first request to get a result needed for a second one.
Here is the first command:
MongoDB -prompt-:PRIMARY> db.Collection.find({"_p_unit":"TopCollection$npsV9rp1Gg","Order":2},{"_id":0,"AUDIO":1})
{ "AUDIO" : "audio_file_key_1a2b3c_Voice.bin" }
I use this result in the next command:
MongoDB -prompt-:PRIMARY> db.Collection.updateOne({"_p_unit":"TopCollection$BTDGm5LIcX","Order":2},{"$set":{ "AUDIO" : "audio_file_key_1a2b3c_Voice.bin" }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
MongoDB -prompt-:PRIMARY>
Now this is my question:
Is there a way to group the two commands above into one?
Though I tried a few ideas coming up my mind, nothing worked.

Related

Using upsert with the updateOne() method to perform an update operation

I’m using upsert with the updateOne() method as bellow to perform an update.
db.practice.updateOne(
{“title”:“Night Life”},
{$set: detail},
{upsert: true}
)
My query returns the following:
{
"acknowledged" : true,
"matchedCount" : 0,
"modifiedCount" : 0,
"upsertedId" : ObjectId("5f8884fed29ded706c3c6737")
}
Below is the detail variable:
let detail = {
“title” : “Night Life”,
“year” : 2021,
“rated” : “PG-13”,
“released” : 2021,
“runtime” : 60,
“countries” : [
“USA”,
“UK”
],
“genres” : [
“comedy”,
“drama”
],
“director” : “Alpha Ly”,
“actors” : [
“Alpha Ly”,
“Kris Dasha”,
“Hope Grace”
]
}
When I check my collection in Compass, I don’t see the document with the ObjectId("5f8884fed29ded706c3c6737
However, when I run the following command db.practice.find({"director": "Alpha Ly"}).pretty(),
it returns the entry I've looking for in Compass.
NB: the number of documents in my collection is still the same as created.
What seems to be the problem here. Why Compass is not displaying the entry?
It seems like I was not using the correct database.
In order to execute the command, I was supposed to use the use command followed by the name of my database to switch to my database. Since I didn't, the update query created another collection and inserted the document there. Therefore, I couldn't find it in my database.
Thanks

Why is the this mongodb query slow when it's indexed?

Why is the following query slow when an index is being utilized?
db.foo.count({$and:[{'metadata.source':'WZ'}, {'metadata.source':'ED'}]})
with the index
{
"v" : 1,
"key" : { 'metadata.source" : 1 },
"name" : "metadata.source_1",
"ns" : "bar.foo"
}
where the metadata field is a JSON Array
The following with a single value returns immediately
db.foo.count({'metadata.source':'WZ'})
Update:
I'm using Mongo v3.0.3. Setup is a sharded replica-set with about 12M documents.
I tried the following with the same delay
db.foo.count({'metadata.source' : { $all : ['WZ', 'ED'] }})
When I check db.currentOp(), it shows the following which seems correct:
"planSummary" : "IXSCAN { metadata.source: 1.0 }"
But the numYields is very high and continues to increase. Does this mean the index does not fit into memory and is reading from disk. There should be plenty of memory based on my db.foo.stats(). Anything else I should look for to help diagnose?
This is also using the wiredTiger storage engine which seems to have some noted performance issues. I'm attempting to upgrade to 3.0.7 to see if that resolves the issue.

MongoDb: how to write your mongoDb query result in a file?

While running a query i want a result of that query into another file
My query is running successfully in mongo terminal.
db.questions.find({"question" : {$regex : ".*.*"}},{question :1,_id:0,id:1});
{ "id" : 0, "question" : "Amount was debited from my account, but ticket was not
generated. What should I do now?" }
{ "id" : 1, "question" : "How safe is goCash?" }
{ "id" : 2, "question" : "How referral program and goCash works?" }
Now check following image:
here
By this i can write in any type of file by just adding >> filename.extension
Now the main problem is with this one:
When i use find instead of findOne and use a regular expression, it shows unexpected token
Anyone knows how i can modify it to get the desired result.
You are using "(qoutes) inside the command line. Try using {'question' : { \$regex : '.*'}}.
Further the db.collection.find() method returns a cursor. Redirecting it to a file will just write the cursor json.To access the documents, you need to iterate the cursor.
mongo localhost/database -eval "var cursor = {'question' : { \$regex : '.*'}}; while(cursor.hasNext()){ printjson( cursor.next())}"
All the examples in the blog return result as json format.
You can also use any of the mongo-drivers to write your result to a file.

Find records with a value outside a specific range in MongoDB

I'm trying to find records in MongoDB that are created outside a specific period. The query to search for records inside a specific period is pretty straightforward:
db.test.find({"Published":{'$gt':"2011-08-02", '$lt':"2011-08-06"}})
So naturally, I tried this for "outside" a specific range:
db.test.find({'$not':{"Published":{'$gt':"2011-08-02", '$lt':"2011-08-06"}}})
But this returns an empty result, while there are definately records published then.
What query should I use instead? Can anyone help me? I'm using raw mongo queries.
Thanks in advance
--- UPDATE ---
I found that the following query works, but it doesn't look like the perfect solution:
db.test.find(
{'$or': [
{"Published":{'$lt':"2011-02-02"}},
{"Published":{'$gt':"2011-08-06"}}
]}
)
Is there a cleaner way to do it?
You are putting the $not in the wrong place. Try this:
db.test.find({"Published":{ $not:{$gt:"2011-08-02", $lt:"2011-08-06"} } })
For details, see the MongoDB docs about the $notoperator.
Edit as because of the comment this solution would not work:
> db.dates.find()
{ "_id" : ObjectId("5492d46ef6226b581c80c0a2"), "a" : 1, "date" : "2011-08-04" }
{ "_id" : ObjectId("5492d4e2f6226b581c80c0a3"), "a" : 2, "date" : "2011-08-07" }
> db.dates.find({date:{$not:{$gt:"2011-08-02",$lt:"2011-08-06"}}})
{ "_id" : ObjectId("5492d4e2f6226b581c80c0a3"), "a" : 2, "date" : "2011-08-07" }

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", ...} }