As the title suggests, I am trying to use count() with a find() on a collection but it keeps throwing the error AttributeError: 'Cursor' object has no attribute 'count'.
For reference, I went through this question but count_documents() seems to be tehre for colelctions themselves, and not cursors. The other option mentioned was len(list(cursor)) but I can't use that as it consumes the cursor itself (can't iterate over it after this). I went through a couple more answers, but these seem to be the main ways out.
Moreover, my pymongo version is 4.3.3 which can't be changed due to some restrictions.
Is there any operation I can perform directly on Cursor which doesn't consume it?
Sample code
def temp(col):
return col.find().count()
print(temp(collection))
Thanks!
list() will exhaust the cursor, but save its ouput to a variable and you can access it multiple times, e.g.
records = list(col.find())
num_records = len(records)
for record in records:
# do stuff
Related
from win32com.client import Dispatch
oAccess = Dispatch("Access.Application")
oAccess.Visible = False
oAccess.OpenCurrentDatabase(my_db)
oDB = oAccess.CurrentDB
for tbl in oDB.TableDefs:
print(table.Name)
tbl.RefreshLink
I've also done:
for tbl in oAccess.TableDefs:
print(table.Name)
tbl.RefreshLink
Error: 'function' object has no attribute 'TableDefs'
I'm starting to understand how to manipulate Windows using win32com, but for some reason it seems like ".TableDefs" isn't recognized. Am I going about it the wrong way?
I know this can be done in VBA. I've been tasked with switching everything over to Python.
Your first error, here, is that VBA knows CurrentDb is a method, and can't assign a method to a variable, so it invokes the method.
Python, however, has 0 problems with assigning a method to a variable, so just does so. Which means you need the parentheses to invoke the method:
oDB = oAccess.CurrentDb()
This fixes the immediate issue (same goes for tbl.RefreshLink, this likely should be tbl.RefreshLink()).
Furthermore, you never define table, only tbl, so you likely want print(tbl.Name).
I am trying to perform a Firebase Query, am using python and firebase-admin, using only startAt brings no results, adding end at throws the error shown below. Thanks for any guidance.
Query
self.users = self.ref.child("products").order_by_child(chosenCriteria).start_at(searchWord).endAt(searchWord+"\uf8ff").get()
Error
self.users = self.ref.child("products").order_by_child(chosenCriteria).start_at(searchWord).endAt(searchWord+"\uf8ff").get()
AttributeError: 'Query' object has no attribute 'endAt'
This reference has helped me, I have had to restructure my queries, though am still not certain why it didn't work the above way
https://morioh.com/p/a593f973aff0
so I created a Cursor object by having
cdb=self.mongo['bleh_bleh_bleh_setup_here']
data=cdb[collection].find(query_commands_here)
Don't worry about the syntax above. Just assume that I can successfully create such cursor object
I know I can do a for loop to iterate through the object, but all I want is the very first item of this object. Is there a more efficient way than looping through?
EDIT:
to make things more clear, the 'bleh_bleh_bleh_setup_here' is simply path to connect to the desired mongoDB, and 'query_commands_here' are queries like {field1:{'$gt':num1}, field2:{'$ne':num2}} that sort of things. The line
data=cdb[collection].find(query_commands_here)
will give me a Cursor object that I can iterate with a for loop. So things like
for item in data:
print item
will print out each of the entry in the object. It works nicely. However, according to the documentation, this cursor object should have method called .hasNext(), which should return True if there's a next entry. So far, I haven't found a way to get it to work for some odd reason. data.next() does give me an entry though. I want to make sure I can have that condition to make sure I don't call .next() for a cursor object that contains nothing, though I don't foresee this kind of situation happening, but I would assume it'd occur at some point.
.find_one() would return you a single document matching the criteria:
cdb[collection].find_one(query_commands_here)
Note that the PyMongo Cursor does not have a hasNext() method. What I would do is to call cursor.next() and handle the StopIteration exception:
try:
record = cursor.next()
except StopIteration:
print("Empty cursor!")
You can also do the following (without having to handle the StopIteration exception):
cur = cdb[collection].find(query_commands_here)
record = next(cur, None)
if record:
# Do your thing
This works because python's built in next() will return the default value when it hits the end of the iterator.
I'm writing a quick and dirty maintenace script to delete some rows and would like to avoid having to bring my ORM classes/mappings over from the main project. I have a query that looks similar to:
address_table = Table('address',metadata,autoload=True)
addresses = session.query(addresses_table).filter(addresses_table.c.retired == 1)
According to everything I've read, if I was using the ORM (not 'just' tables) and passed in something like:
addresses = session.query(Addresses).filter(addresses_table.c.retired == 1)
I could add a .delete() to the query, but when I try to do this using only tables I get a complaint:
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 2146, in delete
target_cls = self._mapper_zero().class_
AttributeError: 'NoneType' object has no attribute 'class_'
Which makes sense as its a table, not a class. I'm quite green when it comes to SQLAlchemy, how should I be going about this?
Looking through some code where I did something similar, I believe this will do what you want.
d = addresses_table.delete().where(addresses_table.c.retired == 1)
d.execute()
Calling delete() on a table object gives you a sql.expression (if memory serves), that you then execute. I've assumed above that the table is bound to a connection, which means you can just call execute() on it. If not, you can pass the d to execute(d) on a connection.
See docs here.
When you call delete() from a query object, SQLAlchemy performs a bulk deletion. And you need to choose a strategy for the removal of matched objects from the session. See the documentation here.
If you do not choose a strategy for the removal of matched objects from the session, then SQLAlchemy will try to evaluate the query’s criteria in Python straight on the objects in the session. If evaluation of the criteria isn’t implemented, an error is raised.
This is what is happening with your deletion.
If you only want to delete the records and do not care about the records in the session after the deletion, you can choose the strategy that ignores the session synchronization:
address_table = Table('address', metadata, autoload=True)
addresses = session.query(address_table).filter(address_table.c.retired == 1)
addresses.delete(synchronize_session=False)
In this tutorial it says (http://www.rmunn.com/sqlalchemy-tutorial/tutorial.html) to select all rows of an entity like:
s = products.select()
rs = s.execute()
I get an error saying:
This select object is not bound and does not support direct execution ...
Do I need to reference the session object?
I just want to get all rows in my products table (i've already mapped everything, and I already inserted thousands of rows so that part works)
Since that tutorial is built for SQLALchemy 0.2, it is likely that you aren't using that old of a version. In the latest documentation using the connection and passing the select statement to it is the preferred method. Try this instead:
query = users.select()
result = conn.execute(query)
Ref: http://www.sqlalchemy.org/docs/05/sqlexpression.html#selecting