首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >批量查找mongoDB记录(使用mongoid ruby适配器)

批量查找mongoDB记录(使用mongoid ruby适配器)
EN

Stack Overflow用户
提问于 2011-08-12 22:03:16
回答 6查看 20.3K关注 0票数 42

使用带有mongoid适配器的Rails3和mongoDB,我如何批量查找mongo DB?我需要获取特定mongo DB集合中的所有记录,并在solr (用于搜索的初始数据索引)中对它们进行索引。

我遇到的问题是,执行Model.all会抓取所有记录并将它们存储到内存中。然后,当我在solr中对它们进行处理和索引时,我的内存就会耗尽,这个过程就会终止。

我正在尝试做的是在mongo中批量查找,这样我就可以一次迭代超过1000条记录,将它们传递给solr进行索引,然后处理下1000条记录,依此类推。

我目前使用的代码是这样做的:

代码语言:javascript
复制
Model.all.each do |r|
  Sunspot.index(r)
end

对于大约有150万条记录的集合,这会消耗8+ GB的内存并终止进程。在ActiveRecord中,有一个find_in_batches方法,它允许我将查询分成可管理的批处理,从而防止内存失控。然而,对于mongoDB/mongoid,我似乎找不到这样的东西。

我希望能够做这样的事情:

代码语言:javascript
复制
Model.all.in_batches_of(1000) do |batch|
  Sunpot.index(batch)
end

这将通过每次只做一个可管理的问题集来缓解我的内存问题和查询困难。然而,关于在mongoDB中进行批处理查找的文档很少。我看到很多关于批量插入的文档,但没有批量查找。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-12-23 10:29:19

使用Mongoid,您不需要手动批处理查询。

在Mongoid中,Model.all返回一个Mongoid::Criteria实例。在此条件下调用#each时,Mongo驱动程序游标被实例化并用于迭代记录。这个底层的Mongo驱动程序游标已经批处理了所有记录。默认情况下,batch_size为100。

有关此主题的更多信息,请阅读this comment from the Mongoid author and maintainer

总而言之,您可以这样做:

代码语言:javascript
复制
Model.all.each do |r|
  Sunspot.index(r)
end
票数 91
EN

Stack Overflow用户

发布于 2014-05-17 01:26:52

如果您正在迭代一个集合,其中每条记录都需要进行大量处理(即查询每个项的外部API ),那么游标可能会超时。在这种情况下,您需要执行多个查询,以便不使游标保持打开状态。

代码语言:javascript
复制
require 'mongoid'

module Mongoid
  class Criteria
    def in_batches_of(count = 100)
      Enumerator.new do |y|
        total = 0

        loop do
          batch = 0

          self.limit(count).skip(total).each do |item|
            total += 1
            batch += 1
            y << item
          end

          break if batch == 0
        end
      end
    end
  end
end

下面是一个辅助方法,您可以使用它来添加批处理功能。它的使用方法如下:

代码语言:javascript
复制
Post.all.order_by(:id => 1).in_batches_of(7).each_with_index do |post, index|
  # call external slow API
end

只要确保你的查询总是有一个order_by就行了。否则,分页可能不会执行您想要的操作。此外,我会坚持使用100个或更少的批次。正如在被接受的答案中所说,Mongoid查询是以100个为一批的,所以在进行处理时,您永远不会想让游标保持打开状态。

票数 7
EN

Stack Overflow用户

发布于 2013-03-05 03:33:32

将批次发送到太阳黑子也更快。我是这样做的:

代码语言:javascript
复制
records = []
Model.batch_size(1000).no_timeout.only(:your_text_field, :_id).all.each do |r|
  records << r
  if records.size > 1000
    Sunspot.index! records
    records.clear
  end
end
Sunspot.index! records

no_timeout:防止光标断开连接(默认情况下,在10分钟后)

only:只选择id和字段,它们实际上是索引的

batch_size:获取1000个条目,而不是100个

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7041224

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档