variables not set in mongo shell - mongodb

I am trying to work with mongo shell and I am having challenges in storing the value inside of mongo shell
when I find a user in the document users, i store it in the variable doc
> var doc = db.users.find({"username":"anil"});
When I type doc in the mongo shell i see the json object
> doc
{ "_id" : ObjectId("57325aaa48d9231b11e5cb81"), "username" : "anil", "email" : "mongodb#gmail.com" }
However when I type doc again, i dont see anything. its gone.. what am I doing wrong here ?
> doc
>
It might be something simple but I am not getting it. Can someone point out what I am doing wrong ?

This because find returns a cursor and you can only consume all the value once. Here because you filter your document based on _id value, in the return cursor you only have one document which is consumed the first time you time. If you need to iterate your result many times, you will need to return an array that contains all the documents from the cursor using toArray, but in your case what you need is findOne

when you open a mongo shell it tries to find a mongod server and connects to test by default. when you assign some variable in mongo shell to some document in mongod, it actually fetches the document from the database, to get the same result again you need to connect to the database again (means you need to type var doc = db.users.find({"username":"anil"}); again). Unlike the scenario where you define var doc = 4 in shell and typing doc will return 4 every time.
If you want to stop transmission at the beginning and do some processing then you need to add null after it like
var doc = db.users.find({"username":"anil"});null;
// do your work on doc
an ex.

One other option could be to use the next() function of the find() cursor. This will give the value of the first record in to the variable and it will persist. Then any required operation can be done on the variable.

Related

find_one query returns just the fields instead of an entry

I'm currently trying to use pymongo's find_one query. When I run the Mongo Shell and execute a findOne query, it get a document that is returned. However when I try using pymongo's find_one query, I always seem to get just the field names instead of an actual entry.
#app.route("/borough/manhattan/")
def manhattan():
restaurantmanhattan = restaurants.find_one({'borough':'Manhattan'})
json_restaurantmanhattan = []
for restaurant in restaurantmanhattan:
json_restaurantmanhattan.append(restaurant)
json_restaurantmanhattan = json.dumps(json_restaurantmanhattan)
return json_restaurantmanhattan
Once I navigate to http://0.0.0.0:5000/borough/manhattan/ I get the following:
["cuisine","borough","name","restaurant_id","grades","address","_id"]
I believe I should be seeing a document entry that meets the query that it has Manhattan listed in the borough.
I'm at a loss as to how I should be writing the query to return that.
Can anyone explain what I'm seeing?
There are many things wrong with your view.
First as you may already know, find_one return a single document as Python dictionary. So in your for loop, you iterating the dictionary keys.
You really do not need that for loop.
import json
#app.route("/borough/manhattan/")
def manhattan():
restaurant_manhattan = restaurants.find_one({'borough':'Manhattan'})
return json.dumps(restaurant_manhattan)

Does MongoDB simplify query logic?

Are the following logical equivalent queries handled by the server differently?
{"Name":"1"}
{$and:[{"Name":"1"},{$or:[{"Name":"1"},{"Tag":"a"}]}]}
Since the second query include the "Tag" field, does it affect index usage?
If you want to experiment and see what mongo is doing for each query you can use an explainable object in the mongo shell.
You can create it with a cursor (https://docs.mongodb.org/manual/reference/method/cursor.explain/):
db.example.find({a:17, b:55}).sort({b:-1}).explain()
Or you can create an explainable object and execute queries with it (https://docs.mongodb.org/v3.0/reference/explain-results/#explain-output):
var exp = db.example.explain()
exp.help() // see what you can do with it
exp.find({a:17, b:55}).sort({b:-1}) // execute query over the object
I cannot answer your question since you do not provide information about the indexes defined in your database, but using this you can see it by yourself in the "queryPlanner" section. If it's using an index it shows "IXSCAN" at "stage" field.

Retrieving the newly-generated _id when inserting through Shell

This might be trivial, but when running 'insert' from Mongodb shell, I can't seem to retrieve the newly-generated _id :
db.coll.insert({someField:"someValue"});
var theId=??? /* How to get the _id of my newly inserted object? */
I know how to retrieve it through language specific drivers (java, node.js) but not from the Shell. So far I eliminated the following :
var x=db.coll.insert(...)
print(x);
// Doesn't work: x is undefined
var doc={...}
db.coll.insert(doc);
print(doc._id)
// Doesn't work, prints undefined
Thank you
Try this:
var doc={...}
db.coll.save(doc);
print(doc._id)
Note that db.collection.save() will update a document if it finds a match by _id. In your case, it will do an insert.
Honestly, I'm not quite sure why db.collection.insert() doesn't populate _id in your in-memory document...

Pymongo sort error

I have been trying to sort documents in Mongo collection by ObjectId in descending order from Pymongo and use the last added record using this code
record = collection.find({}).sort('_id', -1).limit(1)
However, I am getting 'expected a character buffer object'error. Not sure what is happening here.
Also, if anyone can think of a better way to get the last added record from mongo collection using Pymongo, it will be great help.
for item in collection.find().sort("_id", pymongo.DESCENDING).limit(1):
# do something with your item.
This error indicates to me that your "collection" variable holds a string, not a PyMongo Collection instance. I need to see the code that sets the "collection" variable to know what mistake you're making. But let's start from the top:
import pymongo
client = pymongo.MongoClient()
collection = client.db
cursor = collection.find({}).sort('_id', -1).limit(1)
record = cursor.next()
This will get you a recently-added document, but not always the most recently added. The timestamp portion of an ObjectId is only precise to one second, and since it's generated on the client machine that inserts the document, ObjectId is subject to clock skew.
If and only if the collection is capped, you can reliably get the last document like:
cursor = collection.find({}).sort('$natural', -1).limit(1)
record = cursor.next()

Getting an item count with MongoDB C# driver query builder

Using the c# driver for MongoDB I can easily construct a query against which I can then add SetSkip() and SetLimit() parameters to constrict the result set to a certain size.
However I'd like to be able to know what item count of the query would be before applying Skip and Take without executing the query and loading the entire result set (which could be huge) into memory.
It looks like I can do this with MongoDB directly through the shell by using the count() command. e.g.:
db.item.find( { "FieldToMatch" : "ValueToMatch" } ).count()
Which just returns an integer and that's exactly what I want. But I can't see a way in the documentation of doing this through the C# driver. Is it possible?
(It should be noted that we're already using the query builder extensively, so ideally I'd much rather do this through the query builder than start issuing commands down to the shell through the driver, if that's possible. But if that's the only solution then an example would be helpful, thanks.)
Cheers,
Matt
You can do it like this:
var server = MongoServer.Create("mongodb://localhost:27020");
var database = server.GetDatabase("someDb");
var collection = database.GetCollection<Type>("item");
var cursor = collection.Find(Query.EQ("FieldToMatch" : "ValueToMatch"));
var count = cursor.Count();
Some notes:
You should have only one instance of server (singleton)
latest driver version actually returns long count instead of int
Cursor only fetches data once you iterate
You can configure a lot of things like skip, take, specify fields to return in cursor before actually load data (start iteration)
Count() method of cursor loads only document count
I'm using the Driver 2.3.0 and now is also possible to do that like this:
...
IMongoCollection<entity> Collection = db.GetCollection<entity>(CollectionName);
var yourFilter = Builders<entity>.Filter.Where(o => o.prop == value);
long countResut = Collection.Count(yourFilter);