PyMongo Cursor Iteration

混江龙づ霸主 提交于 2019-12-07 17:35:24

问题


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 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



回答3:


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)



回答4:


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


来源:https://stackoverflow.com/questions/10424078/pymongo-cursor-iteration

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