【问题标题】:PyMongo Cursor IterationPyMongo 光标迭代
【发布时间】:2012-05-12 12:53:26
【问题描述】:

我正在寻找在 python 中创建和处理游标的方式,就像游标在 mongo 中本机工作的方式一样。我知道预期的方法是执行“result = collection.find()”并执行“for record in result”,但我希望将迭代功能包装在一个类中。我希望能够创建一个新的类对象并调用一个函数,例如init_cursor() 建立数据库连接并执行返回游标的查找。然后我希望有一个 get_next() 函数,该函数将移动到下一个结果并根据结果设置类数据成员。这是伪代码:

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

这样我就可以简单地调用:

obj.get_next()
age = obj.age
gender = obj.gender

或其他一些帮助功能从每个文档中提取数据

【问题讨论】:

  • 如果你要包装一个游标,你应该建立一些机制来每次刷新连接。不应像在 init 中那样持久地保持光标。它必须被丢弃和刷新。我们的想法是获取光标并将结果提取到分离的对象中。

标签: python mongodb pymongo


【解决方案1】:

我不明白你展示的内容是不是更方便:

col = pymongo.Connection().db.collection
cur = col.find({})

obj = next(cur, None)
if obj:
    age = obj['age']
    gender = obj['gender']

不清楚这个包装器有什么帮助。另外,如果你真正追求的是 ORM,那么当它存在时不要重新发明轮子:http://mongoengine.org/

【讨论】:

  • 感谢 mongoengine,不知道它的存在。包装器本质上允许我加载文档并根据加载的对象派生功能,以便抽象暴露给使用该类的人的对象。举个例子:我有一组关键对象,该类遍历这些对象以确定最可行的对象。公共函数调用只是 get_key()。
【解决方案2】:

你应该使用python迭代器协议,你的类可以是这样的

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

那你就可以这样迭代了

for c in DataIter():
    age = c.age
    gender = c.gender

【讨论】:

    【解决方案3】:

    您可以使用类似于您已经发布的内容来完成此操作。 PyMongo 游标没有 haveNext 方法,但它们有一个 next 方法,该方法要么返回下一个文档,要么引发 StopIteration(这是由 Python 迭代器协议指定的)。

    您还可以更进一步:您可以使用__getattr__,而不是将文档中的值分配给类的属性,它实现了 Python 类的属性查找。

    把它们放在一起,你最终可能会得到这样的结果:

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

      这就是我最终的结果:

      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
      

      【讨论】:

      • 保持打开光标不是一个坏主意吗?我认为它们应该按需创建、使用并在您提取结果后丢弃?
      猜你喜欢
      • 2013-07-06
      • 2016-12-31
      • 1970-01-01
      • 2021-11-12
      • 2018-04-14
      • 1970-01-01
      • 2020-02-04
      • 2013-07-29
      • 2011-07-25
      相关资源
      最近更新 更多