mongoDB 레코드 일괄 찾기(mongoid 루비 어댑터 사용)
mongoid 어댑터와 함께 레일 3 및 mongoDB를 사용하여 mongo DB를 일괄 검색하려면 어떻게 해야 합니까?특정 mongo DB 컬렉션의 모든 레코드를 가져와 solr(검색을 위한 데이터의 초기 인덱스)로 인덱싱해야 합니다.
제가 겪고 있는 문제는 모델을 하는 것입니다.모두가 모든 기록을 수집하여 메모리에 저장합니다.그리고 나서 제가 그것들을 처리하고 솔라 색인을 작성할 때, 제 기억은 다 소모되고 그 과정은 사라집니다.
제가 하려는 것은 mongo에서 발견한 것을 일괄 처리해서 한 번에 1,000개 이상의 레코드를 반복해서 솔러 인덱스에 전달하고 다음 1,000개를 처리하는 것입니다.
제가 현재 가지고 있는 코드는 다음과 같습니다.
Model.all.each do |r|
Sunspot.index(r)
end
약 150만 개의 레코드가 있는 컬렉션의 경우 8GB 이상의 메모리를 소비하고 프로세스를 중단합니다.ActiveRecord에는 find_in_batchs 메서드가 있어 쿼리를 관리 가능한 배치로 청크업하여 메모리를 제어할 수 없게 합니다.하지만 mongoDB/mongoid에 대해서는 이런 것을 찾을 수 없을 것 같습니다.
저는 다음과 같은 일을 할 수 있기를 바랍니다.
Model.all.in_batches_of(1000) do |batch|
Sunpot.index(batch)
end
그러면 매번 관리 가능한 문제 세트만 수행하여 메모리 문제와 쿼리 문제를 완화할 수 있습니다.그러나 mongoDB에서 배치 찾기를 수행하는 경우에는 설명서가 거의 없습니다.배치 삽입을 수행하는 것에 대한 문서는 많이 볼 수 있지만 배치 찾기는 그렇지 않습니다.
Mongoid를 사용하면 쿼리를 수동으로 배치할 필요가 없습니다.
Mongoid에서,Model.all
를 반환합니다.Mongoid::Criteria
사례.부르면 바로#each
이 기준에서 Mongo 드라이버 커서는 인스턴스화되어 레코드를 반복하는 데 사용됩니다.이 기본 Mongo 드라이버 커서는 이미 모든 레코드를 배치합니다.기본적으로batch_size
100입니다.
이 항목에 대한 자세한 내용은 Mongoid 작성자 및 유지 관리자의 설명을 참조하십시오.
요약하면 다음과 같은 작업을 수행할 수 있습니다.
Model.all.each do |r|
Sunspot.index(r)
end
각 레코드가 많은 처리(즉, 각 항목에 대한 외부 API 쿼리)를 필요로 하는 컬렉션을 반복하는 경우 커서가 시간 초과될 수 있습니다.이 경우 커서가 열려 있지 않도록 여러 쿼리를 수행해야 합니다.
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
다음은 배치 기능을 추가하는 데 사용할 수 있는 도우미 방법입니다.다음과 같이 사용할 수 있습니다.
Post.all.order_by(:id => 1).in_batches_of(7).each_with_index do |post, index|
# call external slow API
end
항상 문의 사항에 대한 주문_by가 있는지 확인하십시오.그렇지 않으면 페이징이 사용자가 원하는 대로 수행되지 않을 수 있습니다.또한 저는 100개 이하의 배치를 고수할 것입니다.승인된 답변에서 언급한 것처럼 Mongoid는 100개의 묶음으로 쿼리하므로 처리하는 동안 커서를 열어두고 싶지 않습니다.
태양 흑점에도 배치를 보내는 것이 더 빠릅니다.이렇게 해야 합니다.
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
이 끊어지지 .
only
합니다.
batch_size
100100$ 대신 의 항목을 . 1000$ 대 가 져 오 기
배치 처리에 대해서는 잘 모르겠지만, 당신은 이 방법으로 할 수 있습니다.
current_page = 0
item_count = Model.count
while item_count > 0
Model.all.skip(current_page * 1000).limit(1000).each do |item|
Sunpot.index(item)
end
item_count-=1000
current_page+=1
end
하지만 완벽한 장기 솔루션을 찾고 있다면 추천하지 않을 것입니다.제 앱에서 동일한 시나리오를 어떻게 처리했는지 설명하겠습니다.일괄 작업을 하는 대신,
솔러 인덱스를 업데이트하는 레스크 작업을 만들었습니다.
class SolrUpdator @queue = :solr_updator def self.perform(item_id) item = Model.find(item_id) #i have used RSolr, u can change the below code to handle sunspot solr = RSolr.connect :url => Rails.application.config.solr_path js = JSON.parse(item.to_json) solr.add js end
끝.
항목을 추가한 후 재큐 대기열에 항목을 넣었습니다.
Resque.enqueue(SolrUpdator, item.id.to_s)
- 이상입니다, 레스크를 시작하면 모든 것을 처리할 것입니다.
@Ryan McGeary가 말했듯이, 당신은 쿼리를 일괄 처리하는 것에 대해 걱정할 필요가 없습니다.그러나 개체를 한 번에 하나씩 인덱싱하는 것은 개체를 배치하는 것보다 훨씬 느립니다.
Model.all.to_a.in_groups_of(1000, false) do |records|
Sunspot.index! records
end
다음 사항이 도움이 될 것입니다. 사용해 보십시오.
Model.all.in_groups_of(1000, false) do |r|
Sunspot.index! r
end
언급URL : https://stackoverflow.com/questions/7041224/finding-mongodb-records-in-batches-using-mongoid-ruby-adapter
'programing' 카테고리의 다른 글
Postgre를 변경하는 방법SQL 사용자 암호? (0) | 2023.05.23 |
---|---|
WPF 창에서 닫기 단추를 숨기는 방법은 무엇입니까? (0) | 2023.05.23 |
Bash에서 플래그가 있는 인수를 가져오는 방법 (0) | 2023.05.23 |
VBA를 사용하여 폴더의 파일을 순환하시겠습니까? (0) | 2023.05.23 |
Postgre에 사용자 정의 유형이 이미 있는지 확인합니다.SQL (0) | 2023.05.23 |