PyMongo Cursor Iteration

匿名 (未验证) 提交于 2019-12-03 00:56:02

问题:

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 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!