mongoid_taggable_with_context 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,71 +1,71 @@
1
- module Mongoid::TaggableWithContext::AggregationStrategy
2
- module MapReduce
3
- extend ActiveSupport::Concern
4
- included do
5
- set_callback :save, :after, :map_reduce_all_contexts!, if: :tags_changed?
6
- set_callback :destroy, :after, :map_reduce_all_contexts!
7
- delegate :aggregation_collection_for, to: "self.class"
8
- end
9
-
10
- module ClassMethods
11
- # Collection name for storing results of tag count aggregation
12
-
13
- def aggregation_database_collection_for(context)
14
- (@aggregation_database_collection ||= {})[context] ||= Moped::Collection.new(self.collection.database, aggregation_collection_for(context))
15
- end
16
-
17
- def aggregation_collection_for(context)
18
- "#{collection_name}_#{context}_aggregation"
19
- end
20
-
21
- def tags_for(context, conditions={})
22
- aggregation_database_collection_for(context).find({value: {"$gt" => 0 }}).sort(_id: 1).to_a.map{ |t| t["_id"] }
23
- end
24
-
25
- # retrieve the list of tag with weight(count), this is useful for
26
- # creating tag clouds
27
- def tags_with_weight_for(context, conditions={})
28
- aggregation_database_collection_for(context).find({value: {"$gt" => 0 }}).sort(_id: 1).to_a.map{ |t| [t["_id"], t["value"].to_i] }
29
- end
30
-
31
- end
32
-
33
- protected
34
-
35
- def changed_tag_arrays
36
- self.class.tag_database_fields & changes.keys.map(&:to_sym)
37
- end
38
-
39
- def tags_changed?
40
- !changed_tag_arrays.empty?
41
- end
42
-
43
- def map_reduce_all_contexts!
44
- self.class.tag_contexts.each do |context|
45
- map_reduce_context!(context)
46
- end
47
- end
48
-
49
- def map_reduce_context!(context)
50
- db_field = self.class.tag_options_for(context)[:db_field]
51
-
52
- map = <<-END
53
- function() {
54
- if (!this.#{db_field})return;
55
- for (index in this.#{db_field})
56
- emit(this.#{db_field}[index], 1);
57
- }
58
- END
59
-
60
- reduce = <<-END
61
- function(key, values) {
62
- var count = 0;
63
- for (index in values) count += values[index];
64
- return count;
65
- }
66
- END
67
-
68
- self.class.map_reduce(map, reduce).out(replace: aggregation_collection_for(context)).time
69
- end
70
- end
71
- end
1
+ module Mongoid::TaggableWithContext::AggregationStrategy
2
+ module MapReduce
3
+ extend ActiveSupport::Concern
4
+ included do
5
+ set_callback :save, :after, :map_reduce_all_contexts!, if: :tags_changed?
6
+ set_callback :destroy, :after, :map_reduce_all_contexts!
7
+ delegate :aggregation_collection_for, to: "self.class"
8
+ end
9
+
10
+ module ClassMethods
11
+ # Collection name for storing results of tag count aggregation
12
+
13
+ def aggregation_database_collection_for(context)
14
+ (@aggregation_database_collection ||= {})[context] ||= Moped::Collection.new(self.collection.database, aggregation_collection_for(context))
15
+ end
16
+
17
+ def aggregation_collection_for(context)
18
+ "#{collection_name}_#{context}_aggregation"
19
+ end
20
+
21
+ def tags_for(context, conditions={})
22
+ aggregation_database_collection_for(context).find({value: {"$gt" => 0 }}).sort(_id: 1).to_a.map{ |t| t["_id"] }
23
+ end
24
+
25
+ # retrieve the list of tag with weight(count), this is useful for
26
+ # creating tag clouds
27
+ def tags_with_weight_for(context, conditions={})
28
+ aggregation_database_collection_for(context).find({value: {"$gt" => 0 }}).sort(_id: 1).to_a.map{ |t| [t["_id"], t["value"].to_i] }
29
+ end
30
+
31
+ end
32
+
33
+ protected
34
+
35
+ def changed_tag_arrays
36
+ self.class.tag_database_fields & changes.keys.map(&:to_sym)
37
+ end
38
+
39
+ def tags_changed?
40
+ !changed_tag_arrays.empty?
41
+ end
42
+
43
+ def map_reduce_all_contexts!
44
+ self.class.tag_contexts.each do |context|
45
+ map_reduce_context!(context)
46
+ end
47
+ end
48
+
49
+ def map_reduce_context!(context)
50
+ db_field = self.class.tag_options_for(context)[:db_field]
51
+
52
+ map = <<-END
53
+ function() {
54
+ if (!this.#{db_field})return;
55
+ for (index in this.#{db_field})
56
+ emit(this.#{db_field}[index], 1);
57
+ }
58
+ END
59
+
60
+ reduce = <<-END
61
+ function(key, values) {
62
+ var count = 0;
63
+ for (index in values) count += values[index];
64
+ return count;
65
+ }
66
+ END
67
+
68
+ self.class.map_reduce(map, reduce).out(replace: aggregation_collection_for(context)).time
69
+ end
70
+ end
71
+ end
@@ -1,116 +1,116 @@
1
- module Mongoid::TaggableWithContext::AggregationStrategy
2
- module RealTime
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- set_callback :save, :after, :update_tags_aggregations_on_save
7
- set_callback :destroy, :after, :update_tags_aggregations_on_destroy
8
- end
9
-
10
- module ClassMethods
11
- def tag_name_attribute
12
- "_id"
13
- end
14
-
15
- # Collection name for storing results of tag count aggregation
16
-
17
- def aggregation_database_collection_for(context)
18
- (@aggregation_database_collection ||= {})[context] ||= Moped::Collection.new(self.collection.database, aggregation_collection_for(context))
19
- end
20
-
21
- def aggregation_collection_for(context)
22
- "#{collection_name}_#{context}_aggregation"
23
- end
24
-
25
- def tags_for(context, conditions={})
26
- aggregation_database_collection_for(context).find({value: {"$gt" => 0 }}).sort(tag_name_attribute.to_sym => 1).to_a.map{ |t| t[tag_name_attribute] }
27
- end
28
-
29
- # retrieve the list of tag with weight(count), this is useful for
30
- # creating tag clouds
31
- def tags_with_weight_for(context, conditions={})
32
- aggregation_database_collection_for(context).find({value: {"$gt" => 0 }}).sort(tag_name_attribute.to_sym => 1).to_a.map{ |t| [t[tag_name_attribute], t["value"].to_i] }
33
- end
34
-
35
- def recalculate_all_context_tag_weights!
36
- tag_contexts.each do |context|
37
- recalculate_tag_weights!(context)
38
- end
39
- end
40
-
41
- def recalculate_tag_weights!(context)
42
- db_field = self.class.tag_options_for(context)[:db_field]
43
-
44
- map = <<-END
45
- function() {
46
- if (!this.#{db_field})return;
47
- for (index in this.#{db_field})
48
- emit(this.#{db_field}[index], 1);
49
- }
50
- END
51
-
52
- reduce = <<-END
53
- function(key, values) {
54
- var count = 0;
55
- for (index in values) count += values[index];
56
- return count;
57
- }
58
- END
59
-
60
- self.class.map_reduce(map, reduce).out(replace: aggregation_collection_for(context)).time
61
- end
62
-
63
- # adapted from https://github.com/jesuisbonbon/mongoid_taggable/commit/42feddd24dedd66b2b6776f9694d1b5b8bf6903d
64
- def tags_autocomplete(context, criteria, options={})
65
- result = aggregation_database_collection_for(context).find({tag_name_attribute.to_sym => /^#{criteria}/})
66
- result = result.sort(value: -1) if options[:sort_by_count] == true
67
- result = result.limit(options[:max]) if options[:max] > 0
68
- result.to_a.map{ |r| [r[tag_name_attribute], r["value"]] }
69
- end
70
- end
71
-
72
- protected
73
-
74
- def get_conditions(context, tag)
75
- {self.class.tag_name_attribute.to_sym => tag}
76
- end
77
-
78
- def update_tags_aggregation(context, old_tags=[], new_tags=[])
79
- coll = self.class.aggregation_database_collection_for(context)
80
-
81
- old_tags ||= []
82
- new_tags ||= []
83
- unchanged_tags = old_tags & new_tags
84
- tags_removed = old_tags - unchanged_tags
85
- tags_added = new_tags - unchanged_tags
86
-
87
-
88
- tags_removed.each do |tag|
89
- coll.find(get_conditions(context, tag)).upsert({'$inc' => {value: -1}})
90
- end
91
- tags_added.each do |tag|
92
- coll.find(get_conditions(context, tag)).upsert({'$inc' => {value: 1}})
93
- end
94
- #coll.find({_id: {"$in" => tags_removed}}).update({'$inc' => {:value => -1}}, [:upsert])
95
- #coll.find({_id: {"$in" => tags_added}}).update({'$inc' => {:value => 1}}, [:upsert])
96
- end
97
-
98
- def update_tags_aggregations_on_save
99
- indifferent_changes = HashWithIndifferentAccess.new changes
100
- self.class.tag_database_fields.each do |field|
101
- next if indifferent_changes[field].nil?
102
-
103
- old_tags, new_tags = indifferent_changes[field]
104
- update_tags_aggregation(field, old_tags, new_tags)
105
- end
106
- end
107
-
108
- def update_tags_aggregations_on_destroy
109
- self.class.tag_database_fields.each do |field|
110
- old_tags = send field
111
- new_tags = []
112
- update_tags_aggregation(field, old_tags, new_tags)
113
- end
114
- end
115
- end
116
- end
1
+ module Mongoid::TaggableWithContext::AggregationStrategy
2
+ module RealTime
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ set_callback :save, :after, :update_tags_aggregations_on_save
7
+ set_callback :destroy, :after, :update_tags_aggregations_on_destroy
8
+ end
9
+
10
+ module ClassMethods
11
+ def tag_name_attribute
12
+ "_id"
13
+ end
14
+
15
+ # Collection name for storing results of tag count aggregation
16
+
17
+ def aggregation_database_collection_for(context)
18
+ (@aggregation_database_collection ||= {})[context] ||= Moped::Collection.new(self.collection.database, aggregation_collection_for(context))
19
+ end
20
+
21
+ def aggregation_collection_for(context)
22
+ "#{collection_name}_#{context}_aggregation"
23
+ end
24
+
25
+ def tags_for(context, conditions={})
26
+ aggregation_database_collection_for(context).find({value: {"$gt" => 0 }}).sort(tag_name_attribute.to_sym => 1).to_a.map{ |t| t[tag_name_attribute] }
27
+ end
28
+
29
+ # retrieve the list of tag with weight(count), this is useful for
30
+ # creating tag clouds
31
+ def tags_with_weight_for(context, conditions={})
32
+ aggregation_database_collection_for(context).find({value: {"$gt" => 0 }}).sort(tag_name_attribute.to_sym => 1).to_a.map{ |t| [t[tag_name_attribute], t["value"].to_i] }
33
+ end
34
+
35
+ def recalculate_all_context_tag_weights!
36
+ tag_contexts.each do |context|
37
+ recalculate_tag_weights!(context)
38
+ end
39
+ end
40
+
41
+ def recalculate_tag_weights!(context)
42
+ db_field = self.class.tag_options_for(context)[:db_field]
43
+
44
+ map = <<-END
45
+ function() {
46
+ if (!this.#{db_field})return;
47
+ for (index in this.#{db_field})
48
+ emit(this.#{db_field}[index], 1);
49
+ }
50
+ END
51
+
52
+ reduce = <<-END
53
+ function(key, values) {
54
+ var count = 0;
55
+ for (index in values) count += values[index];
56
+ return count;
57
+ }
58
+ END
59
+
60
+ self.class.map_reduce(map, reduce).out(replace: aggregation_collection_for(context)).time
61
+ end
62
+
63
+ # adapted from https://github.com/jesuisbonbon/mongoid_taggable/commit/42feddd24dedd66b2b6776f9694d1b5b8bf6903d
64
+ def tags_autocomplete(context, criteria, options={})
65
+ result = aggregation_database_collection_for(context).find({tag_name_attribute.to_sym => /^#{criteria}/})
66
+ result = result.sort(value: -1) if options[:sort_by_count] == true
67
+ result = result.limit(options[:max]) if options[:max] > 0
68
+ result.to_a.map{ |r| [r[tag_name_attribute], r["value"]] }
69
+ end
70
+ end
71
+
72
+ protected
73
+
74
+ def get_conditions(context, tag)
75
+ {self.class.tag_name_attribute.to_sym => tag}
76
+ end
77
+
78
+ def update_tags_aggregation(context, old_tags=[], new_tags=[])
79
+ coll = self.class.aggregation_database_collection_for(context)
80
+
81
+ old_tags ||= []
82
+ new_tags ||= []
83
+ unchanged_tags = old_tags & new_tags
84
+ tags_removed = old_tags - unchanged_tags
85
+ tags_added = new_tags - unchanged_tags
86
+
87
+
88
+ tags_removed.each do |tag|
89
+ coll.find(get_conditions(context, tag)).upsert({'$inc' => {value: -1}})
90
+ end
91
+ tags_added.each do |tag|
92
+ coll.find(get_conditions(context, tag)).upsert({'$inc' => {value: 1}})
93
+ end
94
+ #coll.find({_id: {"$in" => tags_removed}}).update({'$inc' => {:value => -1}}, [:upsert])
95
+ #coll.find({_id: {"$in" => tags_added}}).update({'$inc' => {:value => 1}}, [:upsert])
96
+ end
97
+
98
+ def update_tags_aggregations_on_save
99
+ indifferent_changes = HashWithIndifferentAccess.new changes
100
+ self.class.tag_database_fields.each do |field|
101
+ next if indifferent_changes[field].nil?
102
+
103
+ old_tags, new_tags = indifferent_changes[field]
104
+ update_tags_aggregation(field, old_tags, new_tags)
105
+ end
106
+ end
107
+
108
+ def update_tags_aggregations_on_destroy
109
+ self.class.tag_database_fields.each do |field|
110
+ old_tags = send field
111
+ new_tags = []
112
+ update_tags_aggregation(field, old_tags, new_tags)
113
+ end
114
+ end
115
+ end
116
+ end
@@ -1,52 +1,52 @@
1
- module Mongoid::TaggableWithContext::AggregationStrategy
2
- module RealTimeGroupBy
3
- extend ActiveSupport::Concern
4
- include Mongoid::TaggableWithContext::AggregationStrategy::RealTime
5
-
6
- module ClassMethods
7
- def tag_name_attribute
8
- "_name"
9
- end
10
-
11
- def tags_for(context, group_by, conditions={})
12
- results = if group_by
13
- query(context, group_by).to_a.map{ |t| t[tag_name_attribute] }
14
- else
15
- super(context, conditions)
16
- end
17
- results.uniq
18
- end
19
-
20
- def tags_with_weight_for(context, group_by, conditions={})
21
- results = if group_by
22
- query(context, group_by).to_a.map{ |t| [t[tag_name_attribute], t["value"].to_i] }
23
- else
24
- super(context, conditions)
25
- end
26
-
27
- tag_hash = {}
28
- results.each do |tag, weight|
29
- tag_hash[tag] ||= 0
30
- tag_hash[tag] += weight
31
- end
32
- tag_hash.to_a
33
- end
34
-
35
- protected
36
- def query(context, group_by)
37
- aggregation_database_collection_for(context).find({value: {"$gt" => 0 }, group_by: group_by}).sort(tag_name_attribute.to_sym => 1)
38
- end
39
- end
40
-
41
- protected
42
-
43
- def get_conditions(context, tag)
44
- conditions = {self.class.tag_name_attribute.to_sym => tag}
45
- group_by = self.class.get_tag_group_by_field_for(context)
46
- if group_by
47
- conditions.merge!({group_by: self.send(group_by)})
48
- end
49
- conditions
50
- end
51
- end
1
+ module Mongoid::TaggableWithContext::AggregationStrategy
2
+ module RealTimeGroupBy
3
+ extend ActiveSupport::Concern
4
+ include Mongoid::TaggableWithContext::AggregationStrategy::RealTime
5
+
6
+ module ClassMethods
7
+ def tag_name_attribute
8
+ "_name"
9
+ end
10
+
11
+ def tags_for(context, group_by, conditions={})
12
+ results = if group_by
13
+ query(context, group_by).to_a.map{ |t| t[tag_name_attribute] }
14
+ else
15
+ super(context, conditions)
16
+ end
17
+ results.uniq
18
+ end
19
+
20
+ def tags_with_weight_for(context, group_by, conditions={})
21
+ results = if group_by
22
+ query(context, group_by).to_a.map{ |t| [t[tag_name_attribute], t["value"].to_i] }
23
+ else
24
+ super(context, conditions)
25
+ end
26
+
27
+ tag_hash = {}
28
+ results.each do |tag, weight|
29
+ tag_hash[tag] ||= 0
30
+ tag_hash[tag] += weight
31
+ end
32
+ tag_hash.to_a
33
+ end
34
+
35
+ protected
36
+ def query(context, group_by)
37
+ aggregation_database_collection_for(context).find({value: {"$gt" => 0 }, group_by: group_by}).sort(tag_name_attribute.to_sym => 1)
38
+ end
39
+ end
40
+
41
+ protected
42
+
43
+ def get_conditions(context, tag)
44
+ conditions = {self.class.tag_name_attribute.to_sym => tag}
45
+ group_by = self.class.get_tag_group_by_field_for(context)
46
+ if group_by
47
+ conditions.merge!({group_by: self.send(group_by)})
48
+ end
49
+ conditions
50
+ end
51
+ end
52
52
  end