Mongo Get Count While Returning Whole Documents and Should Queries - mongodb

I am new to Mongo and can't seem to figure out the following after reading posts and the documentation. I am executing the following query:
db.collection.find({'name':'example name'})
Which returns 14 results. I can get the count of correctly by executing:
db.collection.find({'name':'example name'}).count()
However, I want to return the full documents and the count in a single query, similar to the way Elasticsearch does. Is there anyway to do this.
Additionally, is there any equivalence to Elasticsearch's Bool should query (http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html). Essentially I would want to rank the results, so that those with attribute 'onSale=True' are returned before 'onSale=False'.

I'm not sure about your second question, whether MongoDB provides some mechanism equivalent to Elasticsearch's Bool should query.
But for your 1st question, I think you can use Cursor.
var cursor = db.collection.find({'name':'example name'});
Once you've got the cursor, you can use it for getting the count in the following way:
cursor.count()
as well as for getting the documents wrapped in an array in the following way:
cursor.toArray()
For more info on cursor, please see the below mentioned link:
http://docs.mongodb.org/manual/tutorial/iterate-a-cursor/

Related

How can Mongo query specify that two conditions in an array are satisfied at the same time?

For example, the doc is
{'id':'1',
'tag':[{'tag_a':'A',
'score':'10'},
{'tag_b':'B',
'score':'0'}
]
}
I want get the doc that satisfied tag_b get 10 points in my collection. Obviously, I should not get this doc. However, when I use the query below
{$and:[{'tag.tag_b':'B','tag.score':'10'}]}
This doc will appear in the results.
How can I avoid this situation. Thanks!

Pymongo ignoring my limit parameter

I am using Pymongo (v3.5.1) in a Python v3.6.3 Jupyter notebook.
Problem
Even-though I am limiting my results, the db.collection.find() is still retrieving all results before returning
My code:
for post in posts.find({'subreddit_1':"the_donald"}, limit=2):
print(post)
exit
Background
I have imported the Reddit comment data set (RC_2017-01) from files.pushshift.io and created an index on the subreddit field (subreddit_1).
My Indexes
I believe this is caused by the collection having no index on your query term, as exhibited by the line:
planSummary: COLLSCAN
which means that to answer your query, MongoDB is forced to look at each document in the collection one by one.
Creating an index to support your query should help. You can create an index in the mongo shell by executing:
db.posts.createIndex({'subreddit_1': 1})
This is assuming your collection is named posts.
Please note that creating that index would only help with the query you posted. It's likely that different index would be needed for different type of queries.
To read more about how indexing works in MongoDB, check out https://docs.mongodb.com/manual/indexes/
I think you need to change the query, because in find() method 2nd parameter is projection. Find() always return cursor and limit function always works on cursor.
So the syntax should like below:
for post in posts.find({'subreddit_1':"the_donald"})[<start_index>:<end_index>]
print(post)
exit
OR
for post in posts.find({'subreddit_1':"the_donald"}).limit(2)
print(post)
exit
Please read the doc for detail

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)

Pymongo: iterate over all documents in the collection

I am using PyMongo and trying to iterate over (10 millions) documents in my MongoDB collection and just extract a couple of keys: "name" and "address", then output them to .csv file.
I cannot figure out the right syntax to do it with find().forEach()
I was trying workarounds like
cursor = db.myCollection.find({"name": {$regex: REGEX}})
where REGEX would match everything - and it resulted in "Killed".
I also tried
cursor = db.myCollection.find({"name": {"$exist": True}})
but that did not work either.
Any suggestions?
I cannot figure out the right syntax to do it with find().forEach()
cursor.forEach() is not available for Python, it's a JavaScript function. You would have to get a cursor and iterate over it. See PyMongo Tutorial: querying for more than one document, where you can do :
for document in myCollection.find():
print(document) # iterate the cursor
where REGEX would match everything - and it resulted in "Killed".
Unfortunately there's lack of information here to debug on why and what 'Killed' is. Although if you would like to match everything, you can just state:
cursor = db.myCollection.find({"name": {$regex: /.*/}})
Given that field name contains string values. Although using $exists to check whether field name exists would be preferable than using regex.
While the use of $exists operator in your example above is incorrect. You're missing an s in $exists. Again, unfortunately we don't know much information on what 'didn't work' meant to help debug further.
If you're writing this script for Python exercise, I would recommend to review:
PyMongo Tutorial
MongoDB Tutorial: query documents
You could also enrol in a free online course at MongoDB University for M220P: MongoDB for Python Developers.
However, if you are just trying to accomplish your task of exporting CSV from a collection. As an alternative you could just use MongoDB's mongoexport. Which has the support for :
Exporting specific fields via --fields "name,address"
Exporting in CSV via --type "csv"
Exporting specific values with query via --query "..."
See mongoexport usage for more information.
I had no luck with .find().forEach() either, but this should find what you are searching for and then print it.
First find all documents that match what you are searching for
cursors = db.myCollection.find({"name": {$regex: REGEX}})
then iterate it over the matches
for cursor in cursors
print(cursor.get("name"))
The find() methods returns a PyMongo cursor, which is a reference to the result set of a query.
You have to de-reference, somehow, the reference(address).
After that, you will get a better understanding how to manipulate/manage the cursor.
Try the following for a start:
result = db.*collection_name*.find()
print(list(result))
I think I get the question but there's no accurate answer yet I believe. I had the same challenge and that's how I came about this, although, I don't know how to output to a .csv file. For my situation I needed the result in JSON. Here's my solution to your question using mongodb Projections;
your_collection = db.myCollection
cursor = list(your_collection.find( { }, {"name": 1, "address": 1}))
This second line returns the result as a list using the python list() function.
And then you can use jsonify(cursor) or just print(cursor) as a list.
I believe with the list it should be easier to figure how to output to a .csv.

mongoDB Object DBCursor has no method 'sort'

so i created a collection called food with 2 objects that were saved no problem. Using find() yielded no issues either. However, when I entered the following:
db.food.find().sort({averageRating:-1}).select({_id: 1}).limit(2)
I get the error:
JS Error: TypeError: Object DBCursor has no method 'sort'
What am i doing wrong?
Is this what you are looking for?
db.food.find({},{_id:1}).sort({"averageRating":-1}).limit(2);
It selects only 2 id fields ordered by average rating descending.The fields that are to be returned are specified by the second parameter in find(),which in this case is _id.
select is not a valid command in mongoDb as far as I know.
It should be selector, not select. See if that fixes it.
As per shargors' comment, it looks like try.mongodb.org doesn't support sort(). I would recommend downloading and installing mongodb itself, and playing around with the real shell.