Skip to content

Instantly share code, notes, and snippets.

@dblock
Created May 12, 2011 13:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dblock/968519 to your computer and use it in GitHub Desktop.
Save dblock/968519 to your computer and use it in GitHub Desktop.
Improving tags map/reduce with MongoDB 1.8.x
class Tag
include Mongoid::Document
def self.rebuild
tags_before = Hash[ * Tag.all.collect { |tag|
[tag.name, tag]
}.flatten]
map = <<-EOS
function() {
if (this.tags != null) {
this.tags.forEach(function(t) {
emit(t, 1);
});
}
}
EOS
reduce = <<-EOS
function(key, values) {
var count = 0;
values.forEach(function(v) { count += v; });
return count;
}
EOS
tags_mapreduce = nil
tags_mapreduce_coll = nil
if collection.db.connection.server_version >= '1.7.4'
tags_mapreduce = TaggedModel.collection.map_reduce(map, reduce, { :raw => true, :out => { :inline => 1 } })['results']
else
TaggedModel.collection.map_reduce(map, reduce, { out: 'tags_mapreduce' })
tags_mapreduce_coll = Mongoid.master.collection('tags_mapreduce')
tags_mapreduce = tags_mapreduce_coll.find()
end
tags_after = []
tags_mapreduce.each do |tag_mapreduce|
name = tag_mapreduce['_id']
next if name.nil?
name = name.strip
next if name.blank?
tag = tags_before[name]
tag_mapreduce_count = tag_mapreduce['value'].to_i
if ! tag
Tag.create!(name: name, count: tag_mapreduce_count)
else
if (tag_mapreduce_count != tag.count)
tag.update_attribute(:count, tag_mapreduce_count)
end
end
tags_after << tag
end
(tags_before.values - tags_after).each do |tag|
tag.delete
end
tags_mapreduce_coll.drop if tags_mapreduce_coll
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment