check if collection find return a cursor - mongodb

This Meteor code needs to check if a certain document exist in the collection by checking if a cursor is returned, and if no cursor returned then the document does not exist. but it always returns true even if there is no value "alosh" for the text field in any of the documents in the collection
.
Why and how can it be fixed? Thanks
if (myCollection.find({text: 'alosh'}, {limit: 1})) {console.log('found');}
edit
The reason I did not use colllection.findOne is my understanding that it is much slower according to this post

Idea for solution:
You want to understand if there is a document with a certain value for a certain property. You could use:
if(myCollection.findOne({text: 'alosh'})){
console.log("found");}

Add a count. A cursor is always going to be a truthy value as the cursor itself is returned. You need to check the records contained in the cursor so...
if (myCollection.find({text: 'alosh'}, {limit: 1}).count()) {
console.log('found');
}
Because no docs returned is 0 and 0 is falsey this should only return when documents are found

Mongo cursors seem to behave the same as arrays in that an empty cursor (and an empty array) evaluate to true.
So !![] //true and !!collection.find({text : "alosh"}) //true.
BUT collection.findOne({text : "alosh"}) will fail your if - so use that instead
http://docs.meteor.com/#/full/findone

Related

Insert array during mongo insert [duplicate]

there are some questions here regarding how to save a result from a query into a javascript varialbe, but I'm just not able to implement them. The point is that I have a much difficult query, so this question is, in my opinion, unique.
Here is the problem. I have a collection namend "drives" and a key named "driveDate". I need to save 1 variable with the smallest date, and other with the biggest date.
The query for the smallest date is:
> db.drives.find({},{"_id":0,"driveDate":1}).sort({"driveDate":1}).limit(1)
The result is:
{ "driveDate" : ISODate("2012-01-11T17:24:12.676Z") }
how dan I save this to a variable, can I do something like:
tmp = db.drives.find({},{"_id":0,"driveDate":1}).sort({"driveDate":1}).limit(1)
Thanks!!!
Assuming you're trying to do this in the shell:
tmp = db.drives.find({}, {_id:0, driveDate:1}).sort({driveDate:1}).limit(1).toArray()[0]
find returns a cursor that you need to iterate over to retrieve the actual documents. Calling toArray on the cursor converts it to an array of docs.
After some time figuring out, I got the solution. here it is, for future reference:
var cursor = db.drives.find({},{"_id":1}).sort({"driveDate":1}).limit(1)
Then I can get the document from the cursor like this
var myDate = cursor.next()
That's it. Thanks for your help

Mongodb cannot use the part (...) to traverse the element ({...: undefined})]

After upgrade to 3.0 mongo driver i am receiving some new error on update request. For update like this:
db.table.update({_id: .... } , {$set : { "tags.Tag1" : true }});
I am receiving
cannot use the part (tags of tags.Tag1) to traverse the element ({tags: null})]]
The problem is that my updated document already contains default value for tags : null. If I manually remove it from document , update starts to work correctly. It is some new behavior for me , and it is happens after updating mongo driver from 2 to 3 ( not even database itself).
But now I wonder now how to avoid this error. I can of course check if "tags" already defined and only then make $set to element or the whole map. But it means 3 requests vs one old and the other problems like atomicity.
Although it's an old post but I think what you are looking for is the $ positional operator
I am guessing your "tags" is an array. So the above example could be something like
db.table.update({_id: .... } , {$set : { "tags.$.Tag1" : true }});
Hope it helps!
Yes, it can be updated... I had resolved similar problem
Resolved this
db.table.updateById({_id: .... } , {$set : { "levelSpecificData.scale.uom": "feet"}});
5b1f566ed65c7dcc34aaa7d5 MongoError: cannot use the part (scale of levelSpecificData.scale.uom) to traverse the element ({scale: false})
where in my collection 'levelSpecificData.scale' was a Boolean type T/F
I changed the default value type of levelSpecificData.scale to '{}' empty object... Surprisingly it worked fine after changing default values to object, since I want to treat scale as an object reference this solution was all good for it.

mongodb - i cannot update with $pushAll and simple assignment at the same time

the following fails:
db.test.update({_id:102},{$pushAll:{our_days:["sat","thurs","frid"]}, country:"XYZ"}, {upsert:true})
error message: "Invalid modifier specified: country"
The correct way seems to be:
db.test.update({_id:102},{$pushAll:{our_days:["sat","thurs","frid"]}, $set:{country:"XYZ"}}, {upsert:true})
So is it the case that I cannot mix modifiers like "$pushAll" with simple assignments like field:value, in the same update document? Instead I have to use the $set modifier for simple assignments?
Is there anything in the docs that describes this behaviour?
This happens because db.test.update({_id : 1}, {country : 1}) will just change the whole document to country = 1 and thus removing everything else.
So most probably mongo being smart tells you: You want to update specific element and at the same time to remove everything (and that element as well) to substitute it with country = 1. Most probably this is not what you want. So I would rather rise an error.
Regarding the documentation - I think that the best way is to reread mongodb update.

Mongoid: check for existing documents/embedded documents

is there a preferred way to check for existing documents via mongoid?
if i do Model.find('id')', and the id is nil or the document doesn't exist, it throws an exception... i want it to return an empty array.
if i do Model.where(:id => 'id'), and the id is nil, it returns all the documents... i also want it to return an empty array.
and then with Model.criteria(:id => 'id').to_a, for whatever reason never returns a result, even with a valid object id. not sure what is going on there...
but basically with activerecord i would just use the exists? finder method, so i am looking for the mongoid alternative.
In Mongoid 2.0, Following seems to do what you want:
User.all.for_ids('4d9ad01de1607c4bc000001a').entries

How to print out more than 20 items (documents) in MongoDB's shell?

db.foo.find().limit(300)
won't do it. It still prints out only 20 documents.
db.foo.find().toArray()
db.foo.find().forEach(printjson)
will both print out very expanded view of each document instead of the 1-line version for find():
DBQuery.shellBatchSize = 300
MongoDB Docs - Configure the mongo Shell - Change the mongo Shell Batch Size
From the shell you can use:
db.collection.find().toArray()
to display all documents without having to use it.
You can use it inside of the shell to iterate over the next 20 results. Just type it if you see "has more" and you will see the next 20 items.
Could always do:
db.foo.find().forEach(function(f){print(tojson(f, '', true));});
To get that compact view.
Also, I find it very useful to limit the fields returned by the find so:
db.foo.find({},{name:1}).forEach(function(f){print(tojson(f, '', true));});
which would return only the _id and name field from foo.
With newer version of mongo shell (mongosh) use following syntax:
config.set("displayBatchSize", 300)
instead of depreciated:
DBQuery.shellBatchSize = 300
Future find() or aggregate() operations will only return 300 documents per cursor iteration.
I suggest you to have a ~/.mongorc.js file so you do not have to set the default size everytime.
# execute in your terminal
touch ~/.mongorc.js
echo 'DBQuery.shellBatchSize = 100;' > ~/.mongorc.js
# add one more line to always prettyprint the ouput
echo 'DBQuery.prototype._prettyShell = true; ' >> ~/.mongorc.js
To know more about what else you can do, I suggest you to look at this article: http://mo.github.io/2017/01/22/mongo-db-tips-and-tricks.html
In the mongo shell, if the returned cursor is not assigned to a variable using the var keyword, the cursor is automatically iterated to access up to the first 20 documents that match the query. You can set the DBQuery.shellBatchSize variable to change the number of automatically iterated documents.
Reference - https://docs.mongodb.com/v3.2/reference/method/db.collection.find/
show dbs
use your database name
in my case, I'm using - use smartbank
then - show collections - just to check the document collections name.
and finally, db. your collection name.find() or find({}) -
show dbs
use smartbank
show collections
db.users.find() or db.users.find({}) or db.users.find({_id: ObjectId("60c8823cbe9c1c21604f642b")}) or db.users.find({}).limit(20)
you can specify _id:ObjectId(write the document id here) to get the single document
or you can specify limit - db.users.find({}).limit(20)