MongoDB map/reduce를 사용하여 데이터 이전을 "도울"수 있습니다. 불행하게도 완전히 서버 측 마이그레이션을 수행하는 데 사용할 수 없습니다. ---> {_id : post_id를, 값 : {COMMENT_COUNT : (post_id를, {1 COMMENT_COUNT을}) 방출
- 지도 각 주석 : 당신이 올바른 궤도에, 기본적인 생각은하는 것 1 }}
- 값 줄이기 {comment_count : N} N은 총계입니다. ---> {_id : post_id, 값 : {comment_count : N}}
- 출력 옵션 {reduce : 'posts'}을 map/reduce comment_counts의 결과를 게시물 컬렉션으로 되돌립니다.
다소 광범위한 조사가 끝나면 가까이에, 하지만 서버 측 마이그레이션을 완전히 차단하는 문제가 있습니다. 결과의 모양은 {_id : KEY, value : MAP_REDUCE_VALUE}입니다. 우리는 지금이 모양을 고수하고 있습니다. 주변을 둘러 볼 방법이없는 것 같습니다. 따라서이 모양 외부의 전체 원본 문서를 줄이기위한 입력 (이 모양 바깥의 데이터가 누락 됨), 이나 축소 된 결과로이 도형 외부의 문서를 업데이트 할 수 없습니다. 따라서 게시물 모음에 대한 "최종"업데이트는 클라이언트를 통해 프로그래밍 방식으로 수행해야합니다. 이 수정은 좋은 수정 요청 일 것 같습니다.
다음은 Ruby에서 MongoDB map/reduce를 사용하여 모든 comment_count를 계산하는 방법을 보여주는 작업 예제입니다. 그런 다음 프로그래밍 방식으로 map_reduce_results 컬렉션을 사용하여 posts 컬렉션의 comment_count를 업데이트합니다. reduce 함수는 사용 시도에서 제외되었습니다. {reduce : 'posts'}
약간의 실험을 통해 답변을 확인할 수 있습니다. 또는 완전히 작동하지 않는 서버 측 시도를 게시 할 수 있습니다. 원하는 경우 고정 모델로 완성하십시오. Ruby에서 MongoDB map/reduce를 이해하는 데 도움이되기를 바랍니다. (검사 JSON 루비의 혼합 미안)
시험/유닛/comment_test.rb
require 'test_helper'
class CommentTest < ActiveSupport::TestCase
def setup
@map_reduce_results_name = 'map_reduce_results'
delete_all
end
def delete_all
Post.delete_all
Comment.delete_all
Mongoid.database.drop_collection(@map_reduce_results_name)
end
def dump(title = nil)
yield
puts title
Post.all.to_a.each do |post|
puts "#{post.to_json} #{post.comments.collect(&:text).to_json}"
end
end
def generate
(2+rand(2)).times do |p|
post = Post.create(text: 'post_' + p.to_s)
comments = (2+rand(3)).times.collect do |c|
Comment.create(text: "post_#{p} comment_#{c}")
end
post.comments = comments
end
end
def generate_and_migrate(title = nil)
dump(title + ' generate:') { generate }
dump(title + ' migrate:') { yield }
end
test "map reduce migration" do
generate_and_migrate('programmatic') do
Post.all.each do |p|
p.update_attribute :comment_count, p.comments.count
end
end
delete_all
generate_and_migrate('map/reduce') do
map = "function() { emit(this.post_id, {comment_count: 1}); }"
reduce = <<-EOF
function(key, values) {
var result = {comment_count: 0};
values.forEach(function(value) { result.comment_count += value.comment_count; });
return result;
}
EOF
out = @map_reduce_results_name #{reduce: 'posts'}
result_coll = Comment.collection.map_reduce(map, reduce, out: out)
puts "#{@map_reduce_results_name}:"
result_coll.find.each do |doc|
p doc
Post.find(doc['_id']).update_attribute :comment_count, doc['value']['comment_count'].to_i
end
end
end
end
테스트 출력
Run options: --name=test_map_reduce_migration
# Running tests:
programmatic generate:
{"_id":"4fcae3bde4d30b21e2000001","comment_count":null,"text":"post_0"} ["post_0 comment_0","post_0 comment_1","post_0 comment_2"]
{"_id":"4fcae3bde4d30b21e2000005","comment_count":null,"text":"post_1"} ["post_1 comment_1","post_1 comment_0","post_1 comment_2","post_1 comment_3"]
{"_id":"4fcae3bde4d30b21e200000a","comment_count":null,"text":"post_2"} ["post_2 comment_1","post_2 comment_3","post_2 comment_0","post_2 comment_2"]
programmatic migrate:
{"_id":"4fcae3bde4d30b21e2000001","comment_count":3,"text":"post_0"} ["post_0 comment_0","post_0 comment_1","post_0 comment_2"]
{"_id":"4fcae3bde4d30b21e2000005","comment_count":4,"text":"post_1"} ["post_1 comment_1","post_1 comment_0","post_1 comment_2","post_1 comment_3"]
{"_id":"4fcae3bde4d30b21e200000a","comment_count":4,"text":"post_2"} ["post_2 comment_1","post_2 comment_3","post_2 comment_0","post_2 comment_2"]
map/reduce generate:
{"_id":"4fcae3bee4d30b21e200000f","comment_count":null,"text":"post_0"} ["post_0 comment_0","post_0 comment_1"]
{"_id":"4fcae3bee4d30b21e2000012","comment_count":null,"text":"post_1"} ["post_1 comment_2","post_1 comment_0","post_1 comment_1"]
{"_id":"4fcae3bee4d30b21e2000016","comment_count":null,"text":"post_2"} ["post_2 comment_0","post_2 comment_1","post_2 comment_2","post_2 comment_3"]
map_reduce_results:
{"_id"=>BSON::ObjectId('4fcae3bee4d30b21e200000f'), "value"=>{"comment_count"=>2.0}}
{"_id"=>BSON::ObjectId('4fcae3bee4d30b21e2000012'), "value"=>{"comment_count"=>3.0}}
{"_id"=>BSON::ObjectId('4fcae3bee4d30b21e2000016'), "value"=>{"comment_count"=>4.0}}
map/reduce migrate:
{"_id":"4fcae3bee4d30b21e200000f","comment_count":2,"text":"post_0"} ["post_0 comment_0","post_0 comment_1"]
{"_id":"4fcae3bee4d30b21e2000012","comment_count":3,"text":"post_1"} ["post_1 comment_2","post_1 comment_0","post_1 comment_1"]
{"_id":"4fcae3bee4d30b21e2000016","comment_count":4,"text":"post_2"} ["post_2 comment_0","post_2 comment_1","post_2 comment_2","post_2 comment_3"]
.
Finished tests in 0.072870s, 13.7231 tests/s, 0.0000 assertions/s.
1 tests, 0 assertions, 0 failures, 0 errors, 0 skips