2010-02-23 28 views
1

以下不起作用。线程内对resources.next_document的调用返回nil。没有线程的调用按预期工作。Ruby,MongoDB:如何在线程之间共享游标?

任何MongoDB专家都在那里? :P

resources = db[Resource::COLLECTION].find 

    number_of_threads.times do 
    threads << Thread.new do 
     while resource = resources.next_document 
     puts 'one more doc' 
     end 
    end 
    end 

回答

1

虽然驱动程序本身是线程安全的,但个别游标不是,所以不能以您描述的方式可靠地处理数据。

一种可能性是让单个线程遍历文档,将它们交给任意数量的工作线程进行实际处理。

+0

有趣......为什么会在查询中之前或线程产卵后开始不同影响光标如果光标之间共享所有线程? – Alexandre 2010-02-23 16:01:49

+0

kb:看看我的答案,并告诉我你的想法 – Alexandre 2010-02-24 12:29:53

1

这是我最终使用的解决方案:

反馈欢迎

pool = DocumentPool.new(db) 
5.times do 
    Thread.new do 
    while doc = pool.next_document 
     #something cool 
    end 
    end 
end 


class DocumentPool 
    COLLECTION = 'some_collection' 

    def initialize(db) 
    @db = db     
    @first_doc = cursor.next_document  
    end 

    def collection 
    @db[COLLECTION] 
    end 

    def cursor 
    @cursor ||= collection.find 
    end 

    def shift 
    doc = nil 
    if @first_doc 
     doc = @first_doc 
     @first_doc = nil 
    else 
     doc = cursor.next_document  
    end 
    doc 
    end        

    def count 
    collection.count 
    end 
end 
+0

这可能在某些情况下工作,但我不相信它是万无一失的。为此,您需要围绕集合的next_document方法进行同步。 – 2010-02-24 14:37:57

+0

为什么next_document方法需要同步,但不是我自己的“shift”方法不会? – Alexandre 2010-02-24 15:44:04

+0

我不确定这个@first_doc的东西是否有意义。所有这些转变必须与对next_document的调用进行同步。顺便说一下,在示例顶部的示例代码中,您可以调用pool.next_document。我认为你的意思是pool.shift。 – 2010-02-24 15:55:17