mongoid-mirrored 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +25 -2
- data/lib/mongoid-mirrored/helper_methods.rb +5 -5
- data/lib/mongoid-mirrored/mirror/mirror_methods.rb +58 -32
- data/lib/mongoid-mirrored/mirrored_in.rb +8 -5
- data/lib/mongoid-mirrored/root/root_methods.rb +7 -7
- data/lib/mongoid-mirrored/version.rb +1 -1
- data/perf/benchmark.rb +183 -0
- data/spec/functional/mongoid/comment_spec.rb +6 -3
- data/spec/unit/mirror_attributes.rb +34 -0
- metadata +6 -4
- data/lib/performance/performance.rb +0 -161
data/README.md
CHANGED
@@ -122,8 +122,31 @@ Known issues
|
|
122
122
|
|
123
123
|
Performance
|
124
124
|
------------
|
125
|
-
|
126
|
-
|
125
|
+
I ran a [benchmark](https://github.com/angelim/mongoid-mirrored/blob/master/perf/benchmark.rb) on my computer with the following results
|
126
|
+
|
127
|
+
Benchmark for referenced documents
|
128
|
+
|
129
|
+
user system total real
|
130
|
+
creating 10000 comments in 200 posts from root collection 7.820000 0.250000 8.070000 (8.252877)
|
131
|
+
updating 10000 comments from root collection 5.080000 0.250000 5.330000 (5.583467)
|
132
|
+
# traversing posts with comments 10000 times 0.670000 0.010000 0.680000 (0.772653)
|
133
|
+
finding posts from the 1000 newest comments 0.530000 0.040000 0.570000 (0.647710)
|
134
|
+
deleting 10000 comments from root collection 2.710000 0.180000 2.890000 (3.238750)
|
135
|
+
creating 10000 comments in 200 posts from embedding collection 8.270000 0.210000 8.480000 (8.530049)
|
136
|
+
updating 10000 comments from embedding collection 9.830000 0.360000 10.190000 (10.76156)
|
137
|
+
deleting 10000 comments from embedding collection 4.750000 0.240000 4.990000 (5.217647)
|
138
|
+
|
139
|
+
Benchmark for mirrored documents
|
140
|
+
|
141
|
+
user system total real
|
142
|
+
creating 10000 comments in 200 posts from root collection 14.870000 0.450000 15.320000 (15.476777)
|
143
|
+
updating 10000 comments from root collection 25.590000 0.970000 26.560000 (36.910317)
|
144
|
+
# traversing posts with comments 10000 times 0.200000 0.000000 0.200000 (0.211826)
|
145
|
+
finding posts from the 1000 newest comments 0.190000 0.000000 0.190000 (0.198631)
|
146
|
+
deleting 10000 comments from root collection 17.880000 0.820000 18.700000 (21.626592)
|
147
|
+
creating 10000 comments in 200 posts from embedding collection 7.100000 0.340000 7.440000 ( 8.562442)
|
148
|
+
updating 10000 comments from embedding collection 5.030000 0.300000 5.330000 ( 6.058490)
|
149
|
+
deleting 10000 comments from embedding collection 2.540000 0.130000 2.670000 ( 2.733644)
|
127
150
|
|
128
151
|
Credits
|
129
152
|
-------
|
@@ -3,7 +3,7 @@ module Mongoid
|
|
3
3
|
module HelperMethods
|
4
4
|
def extract_options(*args)
|
5
5
|
options = args.extract_options!
|
6
|
-
self.embedding_models = args
|
6
|
+
self.embedding_models = {:all => args, :current => nil}
|
7
7
|
self.embedding_options = options
|
8
8
|
|
9
9
|
# set defaults
|
@@ -24,13 +24,13 @@ module Mongoid
|
|
24
24
|
inverse_of
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
27
|
+
def symbol_to_class(symbol)
|
28
28
|
begin
|
29
|
-
|
29
|
+
symbol.to_s.classify.constantize
|
30
30
|
rescue
|
31
|
-
Object.const_set
|
31
|
+
Object.const_set symbol.to_s.classify, Class.new
|
32
32
|
ensure
|
33
|
-
|
33
|
+
symbol.to_s.classify.constantize
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -2,35 +2,54 @@ module Mongoid
|
|
2
2
|
module Mirrored
|
3
3
|
module MirrorMethods
|
4
4
|
|
5
|
-
def
|
5
|
+
def define_mirror_attributes
|
6
|
+
mirror_klass.class_eval <<-EOF
|
7
|
+
cattr_accessor :mirror_attributes
|
8
|
+
self.mirror_attributes = {
|
9
|
+
:root => {:association => :#{root_association}, :klass => #{self}},
|
10
|
+
:embedding => {
|
11
|
+
:sym => :#{embedding_models[:current]},
|
12
|
+
:id => :#{embedding_models[:current]}_id,
|
13
|
+
:instance => "#{embedding_models[:current]}",
|
14
|
+
:klass => #{symbol_to_class(embedding_models[:current])},
|
15
|
+
:models => #{embedding_models[:all]}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
EOF
|
19
|
+
end
|
20
|
+
|
21
|
+
def embeds_mirror
|
6
22
|
# mongoid macro embedded_in
|
7
23
|
# eg: embedded_in :post, :inverse_of => :comments
|
8
24
|
|
9
25
|
mirror_klass.class_eval <<-EOT
|
10
|
-
embedded_in
|
26
|
+
embedded_in mirror_attributes[:embedding][:sym], :inverse_of => mirror_attributes[:root][:association]
|
11
27
|
EOT
|
12
28
|
end
|
13
29
|
|
14
|
-
def define_after_create_callback
|
30
|
+
def define_after_create_callback
|
15
31
|
unless mirror_klass.instance_methods.include?(:_create_root)
|
16
32
|
mirror_klass.class_eval <<-EOF
|
17
33
|
after_create :_create_root
|
18
34
|
EOF
|
19
35
|
end
|
20
36
|
|
37
|
+
# Comment.collection.insert(attributes.merge(:post_id => post.id))
|
21
38
|
mirror_klass.class_eval <<-EOF
|
22
39
|
def _create_root
|
23
|
-
|
40
|
+
mirror_attributes[:root][:klass].collection.insert(attributes.merge(mirror_attributes[:embedding][:id] => eval(mirror_attributes[:embedding][:instance]).id))
|
24
41
|
end
|
25
42
|
EOF
|
26
43
|
end
|
27
|
-
|
44
|
+
|
45
|
+
def define_after_update_callback
|
28
46
|
unless mirror_klass.instance_methods.include?(:_update_root)
|
29
47
|
mirror_klass.class_eval <<-EOF
|
30
48
|
after_update :_update_root
|
31
49
|
EOF
|
32
50
|
end
|
33
|
-
|
51
|
+
|
52
|
+
# Comment.collection.update({ :_id => id}, '$set' => attributes.except('_id'))
|
34
53
|
mirror_klass.class_eval <<-EOF
|
35
54
|
def _update_root
|
36
55
|
#{@root_klass}.collection.update({ :_id => id }, '$set' => attributes.except('_id'))
|
@@ -38,41 +57,48 @@ module Mongoid
|
|
38
57
|
EOF
|
39
58
|
end
|
40
59
|
|
41
|
-
def define_after_destroy_callback
|
60
|
+
def define_after_destroy_callback
|
42
61
|
unless mirror_klass.instance_methods.include?(:_destroy_root)
|
43
62
|
mirror_klass.class_eval <<-EOF
|
44
63
|
after_destroy :_destroy_root
|
45
64
|
EOF
|
46
65
|
end
|
47
66
|
|
67
|
+
# Comment.collection.remove({ :id => id}, '$set' => attributes)
|
48
68
|
mirror_klass.class_eval <<-EOF
|
49
69
|
def _destroy_root
|
50
|
-
#{@root_klass}.collection.
|
70
|
+
#{@root_klass}.collection.remove({ :_id => id })
|
51
71
|
end
|
52
72
|
EOF
|
53
73
|
end
|
54
74
|
|
55
|
-
def define_after_create_siblings
|
75
|
+
def define_after_create_siblings
|
56
76
|
unless mirror_klass.instance_methods.include?(:_create_siblings)
|
57
77
|
mirror_klass.class_eval <<-EOF
|
58
78
|
after_create :_create_siblings
|
59
79
|
EOF
|
60
80
|
end
|
81
|
+
|
61
82
|
mirror_klass.class_eval <<-EOF
|
62
83
|
def _create_siblings
|
63
|
-
|
84
|
+
mirror_attributes[:embedding][:models].each do |sibling|
|
64
85
|
_sibling = sibling.to_s
|
65
|
-
next if sibling ==
|
86
|
+
next if sibling == mirror_attributes[:embedding][:sym]
|
66
87
|
sibling_klass = sibling.to_s.classify.constantize
|
67
88
|
if self[_sibling+"_id"]
|
68
|
-
sibling_klass.collection.update(
|
89
|
+
sibling_klass.collection.update(
|
90
|
+
{ :_id => self[_sibling+"_id"] },
|
91
|
+
'$push' => {
|
92
|
+
mirror_attributes[:root][:association] => attributes.merge(mirror_attributes[:embedding][:id] => eval(mirror_attributes[:embedding][:instance]).id)
|
93
|
+
}
|
94
|
+
)
|
69
95
|
end
|
70
96
|
end
|
71
97
|
end
|
72
98
|
EOF
|
73
99
|
end
|
74
100
|
|
75
|
-
def define_after_update_siblings
|
101
|
+
def define_after_update_siblings
|
76
102
|
unless mirror_klass.instance_methods.include?(:_update_siblings)
|
77
103
|
mirror_klass.class_eval <<-EOF
|
78
104
|
after_update :_update_siblings
|
@@ -80,23 +106,23 @@ module Mongoid
|
|
80
106
|
end
|
81
107
|
mirror_klass.class_eval <<-EOF
|
82
108
|
def _update_siblings
|
83
|
-
#{embedding_models}.each do |sibling|
|
109
|
+
#{embedding_models[:all]}.each do |sibling|
|
84
110
|
_sibling = sibling.to_s
|
85
|
-
next if sibling ==
|
111
|
+
next if sibling == mirror_attributes[:embedding][:sym]
|
86
112
|
sibling_klass = sibling.to_s.classify.constantize
|
87
113
|
if self[_sibling+"_id"]
|
88
114
|
nested_attr = {}
|
89
|
-
attributes.except(
|
90
|
-
nested_attr["
|
115
|
+
attributes.except(mirror_attributes[:embedding][:id]).each_pair do |k,v|
|
116
|
+
nested_attr[mirror_attributes[:root][:association].to_s + ".$." + k] = v
|
91
117
|
end
|
92
|
-
sibling_klass.collection.update({"
|
118
|
+
sibling_klass.collection.update({mirror_attributes[:root][:association].to_s+"._id" => id}, '$set' => nested_attr )
|
93
119
|
end
|
94
120
|
end
|
95
121
|
end
|
96
122
|
EOF
|
97
123
|
end
|
98
124
|
|
99
|
-
def define_after_destroy_siblings
|
125
|
+
def define_after_destroy_siblings
|
100
126
|
unless mirror_klass.instance_methods.include?(:_destroy_siblings)
|
101
127
|
mirror_klass.class_eval <<-EOF
|
102
128
|
after_destroy :_destroy_siblings
|
@@ -104,12 +130,12 @@ module Mongoid
|
|
104
130
|
end
|
105
131
|
mirror_klass.class_eval <<-EOF
|
106
132
|
def _destroy_siblings
|
107
|
-
|
133
|
+
mirror_attributes[:embedding][:models].each do |sibling|
|
108
134
|
_sibling = sibling.to_s
|
109
|
-
next if sibling ==
|
135
|
+
next if sibling == mirror_attributes[:embedding][:sym]
|
110
136
|
sibling_klass = sibling.to_s.classify.constantize
|
111
137
|
if self[_sibling+"_id"]
|
112
|
-
sibling_klass.collection.update({ :_id => self[_sibling+"_id"] }, '$pull' => {
|
138
|
+
sibling_klass.collection.update({ :_id => self[_sibling+"_id"] }, '$pull' => { mirror_attributes[:root][:association] => { :_id => id}})
|
113
139
|
end
|
114
140
|
end
|
115
141
|
end
|
@@ -117,26 +143,26 @@ module Mongoid
|
|
117
143
|
end
|
118
144
|
|
119
145
|
# Define callbacks for mirror class that don't trigger callbacks on the root class
|
120
|
-
def
|
146
|
+
def define_mirror_callbacks
|
121
147
|
if [:both, :from_mirror].include?(embedding_options[:sync_direction])
|
122
148
|
if embedding_options[:sync_events].include?(:create) || embedding_options[:sync_events] == [:all]
|
123
|
-
define_after_create_callback
|
124
|
-
if embedding_options[:replicate_to_siblings] && embedding_models.size > 1
|
125
|
-
define_after_create_siblings
|
149
|
+
define_after_create_callback
|
150
|
+
if embedding_options[:replicate_to_siblings] && embedding_models[:all].size > 1
|
151
|
+
define_after_create_siblings
|
126
152
|
end
|
127
153
|
end
|
128
154
|
|
129
155
|
if embedding_options[:sync_events].include?(:update) || embedding_options[:sync_events] == [:all]
|
130
|
-
define_after_update_callback
|
131
|
-
if embedding_options[:replicate_to_siblings] && embedding_models.size > 1
|
132
|
-
define_after_update_siblings
|
156
|
+
define_after_update_callback
|
157
|
+
if embedding_options[:replicate_to_siblings] && embedding_models[:all].size > 1
|
158
|
+
define_after_update_siblings
|
133
159
|
end
|
134
160
|
end
|
135
161
|
|
136
162
|
if embedding_options[:sync_events].include?(:destroy) || embedding_options[:sync_events] == [:all]
|
137
|
-
define_after_destroy_callback
|
138
|
-
if embedding_options[:replicate_to_siblings] && embedding_models.size > 1
|
139
|
-
define_after_destroy_siblings
|
163
|
+
define_after_destroy_callback
|
164
|
+
if embedding_options[:replicate_to_siblings] && embedding_models[:all].size > 1
|
165
|
+
define_after_destroy_siblings
|
140
166
|
end
|
141
167
|
end
|
142
168
|
end
|
@@ -8,6 +8,7 @@ module Mongoid
|
|
8
8
|
base.send(:extend, ClassMethods)
|
9
9
|
base.send :cattr_accessor, :embedding_models
|
10
10
|
base.send :cattr_accessor, :embedding_options
|
11
|
+
base.send :cattr_accessor, :mirror_klass
|
11
12
|
end
|
12
13
|
|
13
14
|
module ClassMethods
|
@@ -20,17 +21,19 @@ module Mongoid
|
|
20
21
|
write_fields_with_options { yield }
|
21
22
|
@root_klass = self
|
22
23
|
# creates a Mirrored class for each embedding model
|
23
|
-
embedding_models.each do |embedding_model|
|
24
|
+
embedding_models[:all].each do |embedding_model|
|
25
|
+
self.embedding_models[:current] = embedding_model
|
24
26
|
mirror_klass = Class.new do
|
25
27
|
include Mongoid::Document
|
26
28
|
|
27
29
|
# includes all fields and methods declared when calling mirrored_in
|
28
30
|
class_eval &block
|
29
31
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
self.mirror_klass = mirror_klass
|
33
|
+
define_mirror_attributes
|
34
|
+
define_mirror_callbacks
|
35
|
+
embeds_mirror
|
36
|
+
_embedding_klass = symbol_to_class(embedding_model)
|
34
37
|
|
35
38
|
# Creates the mirrored class Embedding::Root
|
36
39
|
_embedding_klass.const_set self.name, mirror_klass
|
@@ -28,10 +28,10 @@ module Mongoid
|
|
28
28
|
|
29
29
|
# each embedded class will be touched by the callbacks
|
30
30
|
# this should be used with care or write operations could get very slow
|
31
|
-
embedding_models.each do |embedding_model|
|
31
|
+
embedding_models[:all].each do |embedding_model|
|
32
32
|
# attributes that will be used to define the root and embedding classes and instances
|
33
33
|
embedding_string = embedding_model.to_s
|
34
|
-
_embedding_klass = self.class.
|
34
|
+
_embedding_klass = self.class.symbol_to_class(embedding_model)
|
35
35
|
embedding_instance = eval(embedding_string)
|
36
36
|
|
37
37
|
# Only tries to create mirrored document if the embedding instance is given
|
@@ -52,12 +52,12 @@ module Mongoid
|
|
52
52
|
# if the root document changes the embedding document, the mirrored document is deleted from the previous list
|
53
53
|
# and another mirrored document is created for the new embedding document
|
54
54
|
define_method :_update_mirrors do
|
55
|
-
embedding_models.each do |embedding_model|
|
55
|
+
embedding_models[:all].each do |embedding_model|
|
56
56
|
|
57
57
|
# attributes that will be used to define the root and embedding classes and instances
|
58
58
|
embedding_string = embedding_model.to_s
|
59
59
|
embedding_instance = eval(embedding_string)
|
60
|
-
_embedding_klass = self.class.
|
60
|
+
_embedding_klass = self.class.symbol_to_class(embedding_model)
|
61
61
|
|
62
62
|
if embedding_instance
|
63
63
|
if eval("#{embedding_string}_id_changed?")
|
@@ -87,11 +87,11 @@ module Mongoid
|
|
87
87
|
# destroys the mirrored document when the destroy method is called on the root document
|
88
88
|
# or when the root document establishes a relationship with another embedding document
|
89
89
|
define_method :_destroy_mirrors do |changed_embedding_instance = nil|
|
90
|
-
embedding_models.each do |embedding_model|
|
90
|
+
embedding_models[:all].each do |embedding_model|
|
91
91
|
|
92
92
|
# attributes that will be used to define the root and embedding classes and instances
|
93
93
|
embedding_string = embedding_model.to_s
|
94
|
-
_embedding_klass = self.class.
|
94
|
+
_embedding_klass = self.class.symbol_to_class(embedding_model)
|
95
95
|
embedding_instance = eval(embedding_string)
|
96
96
|
if embedding_instance
|
97
97
|
id_to_destroy = changed_embedding_instance || embedding_instance.id
|
@@ -108,7 +108,7 @@ module Mongoid
|
|
108
108
|
index_params << ", :index => true" if embedding_options[:index]
|
109
109
|
index_params << ", :background => true" if embedding_options[:index] && embedding_options[:background_index]
|
110
110
|
|
111
|
-
embedding_models.each do |embedding_model|
|
111
|
+
embedding_models[:all].each do |embedding_model|
|
112
112
|
self.class_eval <<-EOT
|
113
113
|
belongs_to :#{embedding_model} #{index_params}
|
114
114
|
EOT
|
data/perf/benchmark.rb
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
require "mongoid"
|
3
|
+
require "mongoid-mirrored"
|
4
|
+
|
5
|
+
def rand_post(posts)
|
6
|
+
posts[rand(posts.size)]
|
7
|
+
end
|
8
|
+
|
9
|
+
Mongoid.configure do |config|
|
10
|
+
config.master = Mongo::Connection.new.db("mongoid_perf_test")
|
11
|
+
end
|
12
|
+
Mongoid.logger = Logger.new($stdout)
|
13
|
+
|
14
|
+
Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
|
15
|
+
|
16
|
+
class Post
|
17
|
+
include Mongoid::Document
|
18
|
+
include Mongoid::Timestamps
|
19
|
+
|
20
|
+
field :title
|
21
|
+
has_many :comments
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class Comment
|
26
|
+
include Mongoid::Document
|
27
|
+
include Mongoid::Timestamps
|
28
|
+
field :contents
|
29
|
+
|
30
|
+
belongs_to :post, :index => true
|
31
|
+
end
|
32
|
+
|
33
|
+
puts "----------------------------------------------------"
|
34
|
+
puts "Benchmark for referenced documents"
|
35
|
+
puts "----------------------------------------------------"
|
36
|
+
|
37
|
+
Benchmark.bm do |bm|
|
38
|
+
500.times do
|
39
|
+
Post.create
|
40
|
+
end
|
41
|
+
|
42
|
+
posts = Post.all.to_a
|
43
|
+
|
44
|
+
bm.report "creating 10000 comments in 200 posts from root collection" do
|
45
|
+
10000.times do
|
46
|
+
Comment.create(:post => rand_post(posts))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
bm.report "updating 10000 comments from root collection" do
|
51
|
+
Comment.all.each_with_index do |c,i|
|
52
|
+
c.update_attribute(:contents, i)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
bm.report "traversing posts with comments 10000 times" do
|
57
|
+
10000.times do
|
58
|
+
p = rand_post(posts)
|
59
|
+
p.comments.each do |c|
|
60
|
+
(con ||= []) << c.contents
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
bm.report "finding posts from the 1000 newest comments" do
|
66
|
+
titles = []
|
67
|
+
Comment.where(:contents.gt => 9000).each{|c| titles << c.post.title}
|
68
|
+
end
|
69
|
+
|
70
|
+
bm.report "deleting 10000 comments from root collection" do
|
71
|
+
Comment.all.map(&:destroy)
|
72
|
+
end
|
73
|
+
|
74
|
+
bm.report "creating 10000 comments in 200 posts from embedding collection" do
|
75
|
+
10000.times do
|
76
|
+
p = rand_post(posts)
|
77
|
+
p.comments.create
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
bm.report "updating 10000 comments from embedding collection" do
|
82
|
+
posts.each do |p|
|
83
|
+
p.comments.each_with_index do |c,i|
|
84
|
+
c.update_attribute(:contents, i)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
bm.report "deleting 10000 comments from embedding collection" do
|
90
|
+
posts.each do |p|
|
91
|
+
p.comments.map(&:destroy)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
|
97
|
+
|
98
|
+
Object.send :remove_const, "Post"
|
99
|
+
class Post
|
100
|
+
include Mongoid::Document
|
101
|
+
include Mongoid::Timestamps
|
102
|
+
|
103
|
+
field :title
|
104
|
+
embeds_many :comments, :class_name => "Post::Comment"
|
105
|
+
end
|
106
|
+
|
107
|
+
Object.send :remove_const, "Comment"
|
108
|
+
class Comment
|
109
|
+
include Mongoid::Document
|
110
|
+
include Mongoid::Timestamps
|
111
|
+
include Mongoid::Mirrored
|
112
|
+
|
113
|
+
field :contents
|
114
|
+
|
115
|
+
belongs_to :post
|
116
|
+
|
117
|
+
mirrored_in :post, :index => true do
|
118
|
+
field :contents
|
119
|
+
field :counter, :type => Integer
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
puts "----------------------------------------------------"
|
124
|
+
puts "Benchmark for mirrored documents"
|
125
|
+
puts "----------------------------------------------------"
|
126
|
+
Benchmark.bm do |bm|
|
127
|
+
500.times do
|
128
|
+
Post.create
|
129
|
+
end
|
130
|
+
|
131
|
+
posts = Post.all.to_a
|
132
|
+
|
133
|
+
bm.report "creating 10000 comments in 200 posts from root collection" do
|
134
|
+
10000.times do
|
135
|
+
Comment.create(:post => rand_post(posts))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
bm.report "updating 10000 comments from root collection" do
|
140
|
+
Comment.all.each_with_index do |c,i|
|
141
|
+
c.update_attribute(:contents, i)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
bm.report "traversing posts with comments 10000 times" do
|
146
|
+
10000.times do
|
147
|
+
p = rand_post(posts)
|
148
|
+
p.comments.each do |c|
|
149
|
+
(con ||= []) << c.contents
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
bm.report "finding posts from the 1000 newest comments" do
|
155
|
+
titles = []
|
156
|
+
Post.where(:"comments.contents".gt => 9000).each{|p| titles << p.title}
|
157
|
+
end
|
158
|
+
|
159
|
+
bm.report "deleting 10000 comments from root collection" do
|
160
|
+
Comment.all.map(&:destroy)
|
161
|
+
end
|
162
|
+
|
163
|
+
bm.report "creating 10000 comments in 200 posts from embedding collection" do
|
164
|
+
10000.times do
|
165
|
+
p = rand_post(posts)
|
166
|
+
p.comments.create
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
bm.report "updating 10000 comments from embedding collection" do
|
171
|
+
posts.each do |p|
|
172
|
+
p.comments.each_with_index do |c,i|
|
173
|
+
c.update_attribute(:contents, i)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
bm.report "deleting 10000 comments from embedding collection" do
|
179
|
+
posts.each do |p|
|
180
|
+
p.comments.map(&:destroy)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -61,6 +61,9 @@ describe "Comment" do
|
|
61
61
|
c = article.comments.create(:contents => "embedding", :author => "embedding_author")
|
62
62
|
Comment.first.update_attributes(:article_id => Article.create.id, :user_id => User.create.id)
|
63
63
|
article.reload
|
64
|
+
# puts article.inspect
|
65
|
+
# puts article.comments.inspect
|
66
|
+
# puts Comment.all.to_a.inspect
|
64
67
|
article.comments.should be_empty
|
65
68
|
user.reload
|
66
69
|
user.comments.should be_empty
|
@@ -99,7 +102,7 @@ describe "Comment" do
|
|
99
102
|
it "should destroy document in root collection" do
|
100
103
|
c = Comment.create(:article => article, :user => user, :contents => "root", :author => "root_author" )
|
101
104
|
c.destroy
|
102
|
-
Comment.where(:
|
105
|
+
Comment.where(:contents => "root").should be_empty
|
103
106
|
end
|
104
107
|
|
105
108
|
it "should destroy similar document in each embedding collection" do
|
@@ -116,14 +119,14 @@ describe "Comment" do
|
|
116
119
|
it "should destroy document in root collection" do
|
117
120
|
c = article.comments.create(:contents => "embedding", :author => "embedding_author")
|
118
121
|
c.destroy
|
119
|
-
Comment.where(:
|
122
|
+
Comment.where(:contents => "embedding").should be_empty
|
120
123
|
end
|
121
124
|
|
122
125
|
it "should destroy similar document from embedding collection" do
|
123
126
|
c = article.comments.create(:contents => "embedding", :author => "embedding_author")
|
124
127
|
c.destroy
|
125
128
|
article.reload
|
126
|
-
article.comments.where(:
|
129
|
+
article.comments.where(:contents => "embedding").should be_empty
|
127
130
|
end
|
128
131
|
|
129
132
|
it "should destroy document from sibling collections" do
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Mongoid::Mirrored" do
|
4
|
+
|
5
|
+
context "Mirror Attributes" do
|
6
|
+
let(:mirror) { Article::Comment.new }
|
7
|
+
|
8
|
+
it "should define class accessor attribute for root association" do
|
9
|
+
mirror.class.mirror_attributes[:root][:association].should == :comments
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should define class accessor attribute for root class" do
|
13
|
+
mirror.class.mirror_attributes[:root][:klass].should == Comment
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should define class accessor attribute for embedding sym" do
|
17
|
+
mirror.class.mirror_attributes[:embedding][:sym].should == :article
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should define class accessor for mirror embedding class" do
|
21
|
+
mirror.class.mirror_attributes[:embedding][:klass].should == Article
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should define class accessor for mirror embedding id" do
|
25
|
+
mirror.class.mirror_attributes[:embedding][:id].should == :article_id
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should define class accessor for mirror embedding instance" do
|
29
|
+
mirror.class.mirror_attributes[:embedding][:klass].should == "article"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Alexandre Angelim
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-05-
|
17
|
+
date: 2011-05-25 00:00:00 -03:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -81,8 +81,8 @@ files:
|
|
81
81
|
- lib/mongoid-mirrored/mirrored_in.rb
|
82
82
|
- lib/mongoid-mirrored/root/root_methods.rb
|
83
83
|
- lib/mongoid-mirrored/version.rb
|
84
|
-
- lib/performance/performance.rb
|
85
84
|
- mongoid-mirrored.gemspec
|
85
|
+
- perf/benchmark.rb
|
86
86
|
- spec/functional/mongoid/comment_spec.rb
|
87
87
|
- spec/models/article.rb
|
88
88
|
- spec/models/comment.rb
|
@@ -93,6 +93,7 @@ files:
|
|
93
93
|
- spec/unit/associations_spec.rb
|
94
94
|
- spec/unit/callback_specs.rb
|
95
95
|
- spec/unit/index_spec.rb
|
96
|
+
- spec/unit/mirror_attributes.rb
|
96
97
|
- spec/unit/options_spec.rb
|
97
98
|
- spec/unit/shared_fields_spec.rb
|
98
99
|
has_rdoc: true
|
@@ -138,5 +139,6 @@ test_files:
|
|
138
139
|
- spec/unit/associations_spec.rb
|
139
140
|
- spec/unit/callback_specs.rb
|
140
141
|
- spec/unit/index_spec.rb
|
142
|
+
- spec/unit/mirror_attributes.rb
|
141
143
|
- spec/unit/options_spec.rb
|
142
144
|
- spec/unit/shared_fields_spec.rb
|
@@ -1,161 +0,0 @@
|
|
1
|
-
require "benchmark"
|
2
|
-
require "mongoid"
|
3
|
-
|
4
|
-
def rand_post(posts)
|
5
|
-
posts[rand(posts.size)]
|
6
|
-
end
|
7
|
-
|
8
|
-
Mongoid.configure do |config|
|
9
|
-
config.master = Mongo::Connection.new.db("mongoid_perf_test")
|
10
|
-
end
|
11
|
-
Mongoid.logger = Logger.new($stdout)
|
12
|
-
|
13
|
-
Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
|
14
|
-
|
15
|
-
class Post
|
16
|
-
include Mongoid::Document
|
17
|
-
include Mongoid::Timestamps
|
18
|
-
|
19
|
-
field :title
|
20
|
-
# embeds_many :comments, :class_name => "Post::Comment"
|
21
|
-
has_many :comments
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
class Comment
|
26
|
-
include Mongoid::Document
|
27
|
-
include Mongoid::Timestamps
|
28
|
-
field :contents
|
29
|
-
# include Mongoid::Mirrored
|
30
|
-
|
31
|
-
# mirrored_in :post, :belongs => true do
|
32
|
-
# field :contents
|
33
|
-
# field :counter, :type => Integer
|
34
|
-
# end
|
35
|
-
belongs_to :post, :index => true
|
36
|
-
end
|
37
|
-
|
38
|
-
Benchmark.bm do |bm|
|
39
|
-
10000.times do
|
40
|
-
Post.create
|
41
|
-
end
|
42
|
-
|
43
|
-
posts = Post.all.to_a
|
44
|
-
|
45
|
-
bm.report "criando comments da raiz" do
|
46
|
-
10000.times do
|
47
|
-
Comment.create(:post => rand_post(posts))
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
bm.report "atualizando comments da raiz" do
|
52
|
-
Comment.all.each_with_index do |c,i|
|
53
|
-
c.update_attribute(:contents, i)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
bm.report "leitura de var no relacionamento" do
|
59
|
-
posts.each do |p|
|
60
|
-
p.comments.each do |c|
|
61
|
-
(con ||= []) << c.contents
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
bm.report "apagando comments da raiz" do
|
67
|
-
Comment.all.map(&:destroy)
|
68
|
-
end
|
69
|
-
|
70
|
-
bm.report "criando comments do embedded" do
|
71
|
-
10000.times do
|
72
|
-
p = rand_post(posts)
|
73
|
-
p.comments.create
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
bm.report "atualizando comments da embedded" do
|
78
|
-
posts.each do |p|
|
79
|
-
p.comments.each_with_index do |c,i|
|
80
|
-
c.update_attribute(:contents, i)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
bm.report "apagando comments da embedded" do
|
86
|
-
posts.each do |p|
|
87
|
-
p.comments.map(&:destroy)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
|
93
|
-
|
94
|
-
class Post
|
95
|
-
embeds_many :comments, :class_name => "Post::Comment"
|
96
|
-
# Post.collection.create_index "comments._id"
|
97
|
-
end
|
98
|
-
|
99
|
-
class Comment
|
100
|
-
include Mongoid::Mirrored
|
101
|
-
|
102
|
-
mirrored_in :post, :belongs => true do
|
103
|
-
field :contents
|
104
|
-
field :counter, :type => Integer
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
|
109
|
-
Benchmark.bm do |bm|
|
110
|
-
10000.times do
|
111
|
-
Post.create
|
112
|
-
end
|
113
|
-
|
114
|
-
posts = Post.all.to_a
|
115
|
-
|
116
|
-
bm.report "criando comments da raiz" do
|
117
|
-
10000.times do
|
118
|
-
Comment.create(:post => rand_post(posts))
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
bm.report "atualizando comments da raiz" do
|
123
|
-
Comment.all.each_with_index do |c,i|
|
124
|
-
c.update_attribute(:contents, i)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
bm.report "leitura de var no relacionamento" do
|
130
|
-
posts.each do |p|
|
131
|
-
p.comments.each do |c|
|
132
|
-
(con ||= []) << c.contents
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
bm.report "apagando comments da raiz" do
|
138
|
-
Comment.all.map(&:destroy)
|
139
|
-
end
|
140
|
-
|
141
|
-
bm.report "criando comments do embedded" do
|
142
|
-
10000.times do
|
143
|
-
p = rand_post(posts)
|
144
|
-
p.comments.create
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
bm.report "atualizando comments da embedded" do
|
149
|
-
posts.each do |p|
|
150
|
-
p.comments.each_with_index do |c,i|
|
151
|
-
c.update_attribute(:contents, i)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
bm.report "apagando comments da embedded" do
|
157
|
-
posts.each do |p|
|
158
|
-
p.comments.map(&:destroy)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|