MongoCursor在单独的线程中回放

时间:2012-10-23 15:42:41

标签: multithreading mongodb cursor

我有一种情况,其中几个搜索过程并行化为不同的线程。每个线程获取相同的pymongo.cursor.Cusor对象以查看其结果,但每个线程执行不同的处理。我创建了一个演示程序,如下所示:

class SearchProcedure(Thread):

    weight = 0.1

    def __init__(self,weight=None):
        if weight:
            self.weight = float(weight)
        Thread.__init__(self)

    def start(self,query):
        self.query = query
        Thread.start(self)

    def run(self):
        if hasattr(self,'places'):
            for p in self.places.values():
                print p.name

        if hasattr(self,'posts'):
            for s in self.posts.values():
                s.rewind()
                print [(sh['name'],sh['description']) for sh in s]

    def attach_eligible(self,queue,**kwargs):
        self.queue = queue
        for (name,value) in kwargs.items():
            setattr(self,name,value)

attach_eligible方法是将位置和帖子的属性添加到过程对象的位置。同样,posts属性是一组可以迭代的mongo游标。我在运行结果之前使用rewind将光标重置为原始状态,如果另一个线程已经解开它。我们的想法是每个线程将使用不同的标准来搜索对象,然后将其结果发送到queue属性,以便在调用/实例化范围中使用。

第一个线程运行良好,但所有后续线程利用光标输出以下错误:

  File "/usr/local/lib/python2.7/dist-packages/pymongo/cursor.py", line 668, in __send_message
    assert response["starting_from"] == self.__retrieved
AssertionError

看起来,倒退没有效果。这是因为游标是通过引用传入的吗?它们是否也需要包含在队列中以保持锁定状态?用mongo游标甚至可以做这样的事情吗?如果可以的话会很好,因为它会使搜索条件的处理更加高效,同时执行它。

2 个答案:

答案 0 :(得分:1)

除非经过专门设计允许,否则您无法在线程之间自由共享任何更改状态的对象。 pymongo cursor不是为此设计的。

您可以做的是克隆光标,然后为每个线程提供自己的克隆光标副本。请参阅cursor.clone

答案 1 :(得分:0)

详细介绍@JohnnyHK's answer

根据this answer,光标位于服务器端。完成的任何递增操作都反映在服务器端,因此在第二个线程中复制游标(以某种方式)就像在第二个线程中复制URL,而不是对象/对象列表。 即光标是指向数据库中数据的指针,除非在服务器端进行复制,否则不能复制。因此,您应该使用提及的cursor.clone。