可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm looking to create and handle a cursor in python the way cursors natively work in mongo. I know the intended way is to do 'result = collection.find()' and do a 'for record in result' but I'm looking to wrap iteration functionality in a class. I'd like to be able to create a new class object and call a function e.g. init_cursor() to make a db connection and do a find returning a cursor. I would then like the have a get_next() function that would move to the next result and set class data members based on the result. Here's the pesudo-code:
class dataIter(): def __init__(self): self.collection = pymongo.Connection().db.collection self.cursor = self.collection.find({}) #return all self.age = None self.gender = None def get_next(self): if self.cursor.hasNext(): data = self.cursor.next() self.set_data(data) def set_data(self, data): self.age = data['age'] self.gender = data['gender']
This way I would be able to simply call:
obj.get_next() age = obj.age gender = obj.gender
or some other help functions to pull data out of each document
回答1:
I don't understand how what you are showing is any more convenient that just doing:
col = pymongo.Connection().db.collection cur = col.find({}) obj = next(cur, None) if obj: age = obj['age'] gender = obj['gender']
Its not clear how this wrapper is helpful. Also, if what you are really after is an ORM, then don't reinvent the wheel when this exists: http://mongoengine.org/
回答2:
You can use something like what you have posted already to accomplish this. PyMongo cursors don't have a haveNext
method, but they have a next
method which will either return the next document, or raise StopIteration
(this is specified by the Python iterator protocol).
You can also take this a step further: rather than assigning the values from the document to attributes on the class, you can use __getattr__
which implements attribute lookup for Python classes.
Putting it all together, you might end up with something like:
class DataIter(object): def __init__(self, cursor): self._cursor = cursor self._doc = None def next(self): try: self._doc = self._cursor.next() except StopIteration: self._doc = None return self def __getattr__(self, key): try: return self._doc[key] except KeyError: raise AttributeError('document has no attribute %r' % name)
回答3:
Here's what I ended up going with:
class Cursor(object): def __init__(self): # mongo connection self.collection = pymongo.Connection().cursorcollection self.loaded = False self.cursor = None # Cursor calls (for iterating through results) def init_cursor(self): """ Opens a new cursor """ if not self.cursor: self.cursor = self.collection.find({}) def get_next(self): """ load next object """ if self.cursor and self.cursor.alive: self.set_data(next(self.cursor)) return True else: self.cursor = None return False def has_next(self): """ cursor alive? """ if self.cursor and self.cursor.alive: return True else: return False
回答4:
You should use the python iterator protocol, you class can look like this
class DataIter: def __init__(self): self.collection = pymongo.Connection().db.collection self.cursor = self.collection.find({}) #return all self.age = None self.gender = None def __iter__(self): return self def next(self): if self.cursor.hasNext(): data = self.cursor.next() self.set_data(data) return self else: raise StopIteration
Then you can iterate like this
for c in DataIter(): age = c.age gender = c.gender