mongoid 5.4.0 → 6.4.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +3 -3
- data/Rakefile +26 -0
- data/lib/config/locales/en.yml +40 -0
- data/lib/mongoid/atomic/modifiers.rb +2 -2
- data/lib/mongoid/atomic.rb +5 -5
- data/lib/mongoid/attributes/readonly.rb +22 -0
- data/lib/mongoid/attributes.rb +22 -21
- data/lib/mongoid/cacheable.rb +36 -0
- data/lib/mongoid/changeable.rb +36 -0
- data/lib/mongoid/clients/options.rb +55 -250
- data/lib/mongoid/clients/sessions.rb +113 -0
- data/lib/mongoid/clients/storage_options.rb +2 -69
- data/lib/mongoid/clients.rb +10 -63
- data/lib/mongoid/composable.rb +29 -2
- data/lib/mongoid/config.rb +1 -0
- data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
- data/lib/mongoid/contextual/atomic.rb +4 -4
- data/lib/mongoid/contextual/map_reduce.rb +7 -3
- data/lib/mongoid/contextual/memory.rb +9 -4
- data/lib/mongoid/contextual/mongo.rb +65 -30
- data/lib/mongoid/contextual/none.rb +12 -0
- data/lib/mongoid/copyable.rb +13 -6
- data/lib/mongoid/criteria/marshalable.rb +2 -2
- data/lib/mongoid/criteria/modifiable.rb +29 -3
- data/lib/mongoid/criteria/options.rb +25 -0
- data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
- data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
- data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
- data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
- data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
- data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
- data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
- data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
- data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
- data/lib/mongoid/criteria/queryable/extensions/regexp.rb +79 -0
- data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
- data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
- data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
- data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
- data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
- data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
- data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
- data/lib/mongoid/criteria/queryable/key.rb +103 -0
- data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
- data/lib/mongoid/criteria/queryable/mergeable.rb +273 -0
- data/lib/mongoid/criteria/queryable/optional.rb +429 -0
- data/lib/mongoid/criteria/queryable/options.rb +153 -0
- data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
- data/lib/mongoid/criteria/queryable/selectable.rb +689 -0
- data/lib/mongoid/criteria/queryable/selector.rb +212 -0
- data/lib/mongoid/criteria/queryable/smash.rb +104 -0
- data/lib/mongoid/criteria/queryable.rb +87 -0
- data/lib/mongoid/criteria.rb +6 -2
- data/lib/mongoid/document.rb +34 -41
- data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
- data/lib/mongoid/errors/in_memory_collation_not_supported.rb +1 -1
- data/lib/mongoid/errors/invalid_field.rb +2 -2
- data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
- data/lib/mongoid/errors/invalid_relation.rb +66 -0
- data/lib/mongoid/errors/invalid_session_use.rb +24 -0
- data/lib/mongoid/errors.rb +3 -0
- data/lib/mongoid/evolvable.rb +1 -1
- data/lib/mongoid/extensions/big_decimal.rb +17 -8
- data/lib/mongoid/extensions/date.rb +4 -1
- data/lib/mongoid/extensions/decimal128.rb +3 -3
- data/lib/mongoid/extensions/hash.rb +1 -0
- data/lib/mongoid/extensions/regexp.rb +1 -0
- data/lib/mongoid/extensions/string.rb +6 -3
- data/lib/mongoid/extensions/time.rb +4 -1
- data/lib/mongoid/extensions.rb +0 -4
- data/lib/mongoid/factory.rb +2 -1
- data/lib/mongoid/fields/validators/macro.rb +18 -0
- data/lib/mongoid/findable.rb +2 -2
- data/lib/mongoid/indexable.rb +16 -14
- data/lib/mongoid/interceptable.rb +9 -22
- data/lib/mongoid/matchable/all.rb +2 -2
- data/lib/mongoid/matchable/and.rb +3 -3
- data/lib/mongoid/matchable/default.rb +2 -2
- data/lib/mongoid/matchable/elem_match.rb +28 -0
- data/lib/mongoid/matchable/exists.rb +2 -2
- data/lib/mongoid/matchable/gt.rb +4 -2
- data/lib/mongoid/matchable/gte.rb +4 -2
- data/lib/mongoid/matchable/in.rb +2 -2
- data/lib/mongoid/matchable/lt.rb +4 -2
- data/lib/mongoid/matchable/lte.rb +4 -2
- data/lib/mongoid/matchable/ne.rb +2 -2
- data/lib/mongoid/matchable/nin.rb +2 -2
- data/lib/mongoid/matchable/nor.rb +37 -0
- data/lib/mongoid/matchable/or.rb +3 -3
- data/lib/mongoid/matchable/regexp.rb +3 -3
- data/lib/mongoid/matchable/size.rb +2 -2
- data/lib/mongoid/matchable.rb +16 -7
- data/lib/mongoid/persistable/creatable.rb +5 -3
- data/lib/mongoid/persistable/deletable.rb +5 -3
- data/lib/mongoid/persistable/destroyable.rb +1 -5
- data/lib/mongoid/persistable/settable.rb +5 -5
- data/lib/mongoid/persistable/updatable.rb +7 -14
- data/lib/mongoid/persistable/upsertable.rb +2 -1
- data/lib/mongoid/persistable.rb +4 -6
- data/lib/mongoid/persistence_context.rb +220 -0
- data/lib/mongoid/query_cache.rb +67 -23
- data/lib/mongoid/railtie.rb +17 -1
- data/lib/mongoid/railties/controller_runtime.rb +86 -0
- data/lib/mongoid/relations/accessors.rb +3 -0
- data/lib/mongoid/relations/auto_save.rb +12 -4
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
- data/lib/mongoid/relations/counter_cache.rb +15 -5
- data/lib/mongoid/relations/eager/base.rb +3 -3
- data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +2 -2
- data/lib/mongoid/relations/eager/has_many.rb +1 -1
- data/lib/mongoid/relations/eager.rb +6 -11
- data/lib/mongoid/relations/embedded/batchable.rb +20 -18
- data/lib/mongoid/relations/embedded/in.rb +13 -1
- data/lib/mongoid/relations/embedded/many.rb +51 -10
- data/lib/mongoid/relations/embedded/one.rb +14 -1
- data/lib/mongoid/relations/macros.rb +9 -1
- data/lib/mongoid/relations/many.rb +4 -0
- data/lib/mongoid/relations/metadata.rb +3 -3
- data/lib/mongoid/relations/options.rb +2 -2
- data/lib/mongoid/relations/proxy.rb +1 -31
- data/lib/mongoid/relations/referenced/in.rb +19 -10
- data/lib/mongoid/relations/referenced/many.rb +30 -26
- data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
- data/lib/mongoid/relations/referenced/one.rb +15 -1
- data/lib/mongoid/relations/synchronization.rb +12 -12
- data/lib/mongoid/relations/targets/enumerable.rb +24 -4
- data/lib/mongoid/relations/touchable.rb +7 -4
- data/lib/mongoid/reloadable.rb +2 -2
- data/lib/mongoid/scopable.rb +3 -3
- data/lib/mongoid/serializable.rb +1 -1
- data/lib/mongoid/stateful.rb +1 -0
- data/lib/mongoid/tasks/database.rb +3 -2
- data/lib/mongoid/threaded.rb +74 -0
- data/lib/mongoid/traversable.rb +1 -1
- data/lib/mongoid/validatable/uniqueness.rb +1 -2
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid.rb +6 -6
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +18 -3
- data/spec/app/models/agent.rb +2 -0
- data/spec/app/models/album.rb +5 -1
- data/spec/app/models/array_field.rb +7 -0
- data/spec/app/models/artist.rb +21 -0
- data/spec/app/models/band.rb +3 -0
- data/spec/app/models/book.rb +2 -1
- data/spec/app/models/delegating_patient.rb +16 -0
- data/spec/app/models/dokument.rb +1 -0
- data/spec/app/models/ordered_post.rb +5 -0
- data/spec/app/models/oscar.rb +1 -2
- data/spec/app/models/page.rb +1 -1
- data/spec/app/models/person.rb +3 -3
- data/spec/app/models/princess.rb +2 -0
- data/spec/app/models/record.rb +1 -0
- data/spec/app/models/subscription.rb +1 -0
- data/spec/app/models/thing.rb +1 -1
- data/spec/config/mongoid.yml +15 -0
- data/spec/integration/document_spec.rb +22 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +3 -3
- data/spec/mongoid/atomic_spec.rb +5 -5
- data/spec/mongoid/attributes/nested_spec.rb +18 -14
- data/spec/mongoid/attributes/readonly_spec.rb +87 -44
- data/spec/mongoid/attributes_spec.rb +90 -5
- data/spec/mongoid/cacheable_spec.rb +112 -0
- data/spec/mongoid/changeable_spec.rb +58 -0
- data/spec/mongoid/clients/factory_spec.rb +80 -28
- data/spec/mongoid/clients/options_spec.rb +396 -95
- data/spec/mongoid/clients/sessions_spec.rb +334 -0
- data/spec/mongoid/clients_spec.rb +243 -101
- data/spec/mongoid/composable_spec.rb +7 -0
- data/spec/mongoid/config_spec.rb +67 -11
- data/spec/mongoid/contextual/atomic_spec.rb +3 -3
- data/spec/mongoid/contextual/geo_near_spec.rb +1 -0
- data/spec/mongoid/contextual/mongo_spec.rb +275 -22
- data/spec/mongoid/contextual/none_spec.rb +15 -0
- data/spec/mongoid/copyable_spec.rb +13 -4
- data/spec/mongoid/criteria/modifiable_spec.rb +297 -16
- data/spec/mongoid/criteria/options_spec.rb +29 -0
- data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
- data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
- data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
- data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
- data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
- data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
- data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
- data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
- data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
- data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
- data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
- data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
- data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
- data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
- data/spec/mongoid/{extensions/origin → criteria/queryable/extensions}/regexp_raw_spec.rb +2 -2
- data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +90 -0
- data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
- data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
- data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
- data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
- data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
- data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
- data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
- data/spec/mongoid/criteria/queryable/optional_spec.rb +1799 -0
- data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
- data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
- data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +4242 -0
- data/spec/mongoid/criteria/queryable/selector_spec.rb +844 -0
- data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
- data/spec/mongoid/criteria/scopable_spec.rb +81 -0
- data/spec/mongoid/criteria_spec.rb +156 -22
- data/spec/mongoid/document_spec.rb +100 -90
- data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
- data/spec/mongoid/extensions/big_decimal_spec.rb +321 -19
- data/spec/mongoid/extensions/boolean_spec.rb +14 -0
- data/spec/mongoid/extensions/date_spec.rb +2 -6
- data/spec/mongoid/extensions/date_time_spec.rb +2 -6
- data/spec/mongoid/extensions/decimal128_spec.rb +1 -1
- data/spec/mongoid/extensions/float_spec.rb +8 -1
- data/spec/mongoid/extensions/hash_spec.rb +15 -0
- data/spec/mongoid/extensions/integer_spec.rb +8 -1
- data/spec/mongoid/extensions/object_spec.rb +11 -0
- data/spec/mongoid/extensions/regexp_spec.rb +23 -0
- data/spec/mongoid/extensions/string_spec.rb +53 -4
- data/spec/mongoid/extensions/time_spec.rb +2 -6
- data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
- data/spec/mongoid/factory_spec.rb +11 -0
- data/spec/mongoid/fields_spec.rb +1 -1
- data/spec/mongoid/findable_spec.rb +47 -2
- data/spec/mongoid/indexable_spec.rb +15 -3
- data/spec/mongoid/interceptable_spec.rb +85 -19
- data/spec/mongoid/matchable/all_spec.rb +4 -4
- data/spec/mongoid/matchable/and_spec.rb +10 -10
- data/spec/mongoid/matchable/default_spec.rb +12 -12
- data/spec/mongoid/matchable/elem_match_spec.rb +86 -0
- data/spec/mongoid/matchable/exists_spec.rb +5 -5
- data/spec/mongoid/matchable/gt_spec.rb +18 -7
- data/spec/mongoid/matchable/gte_spec.rb +17 -7
- data/spec/mongoid/matchable/in_spec.rb +5 -5
- data/spec/mongoid/matchable/lt_spec.rb +18 -7
- data/spec/mongoid/matchable/lte_spec.rb +18 -7
- data/spec/mongoid/matchable/ne_spec.rb +5 -5
- data/spec/mongoid/matchable/nin_spec.rb +5 -5
- data/spec/mongoid/matchable/nor_spec.rb +209 -0
- data/spec/mongoid/matchable/or_spec.rb +7 -7
- data/spec/mongoid/matchable/regexp_spec.rb +5 -5
- data/spec/mongoid/matchable/size_spec.rb +3 -3
- data/spec/mongoid/matchable_spec.rb +199 -54
- data/spec/mongoid/persistable/creatable_spec.rb +7 -2
- data/spec/mongoid/persistable/deletable_spec.rb +35 -1
- data/spec/mongoid/persistable/destroyable_spec.rb +25 -2
- data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
- data/spec/mongoid/persistable/savable_spec.rb +34 -29
- data/spec/mongoid/persistable/settable_spec.rb +77 -27
- data/spec/mongoid/persistable/updatable_spec.rb +182 -3
- data/spec/mongoid/persistable_spec.rb +16 -16
- data/spec/mongoid/persistence_context_spec.rb +694 -0
- data/spec/mongoid/positional_spec.rb +1 -1
- data/spec/mongoid/query_cache_spec.rb +170 -12
- data/spec/mongoid/relations/accessors_spec.rb +1 -1
- data/spec/mongoid/relations/auto_save_spec.rb +39 -6
- data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +4 -4
- data/spec/mongoid/relations/builders_spec.rb +37 -10
- data/spec/mongoid/relations/counter_cache_spec.rb +64 -3
- data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +16 -0
- data/spec/mongoid/relations/eager_spec.rb +40 -0
- data/spec/mongoid/relations/embedded/many_spec.rb +305 -59
- data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
- data/spec/mongoid/relations/macros_spec.rb +415 -7
- data/spec/mongoid/relations/metadata_spec.rb +15 -1
- data/spec/mongoid/relations/proxy_spec.rb +27 -1
- data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
- data/spec/mongoid/relations/referenced/many_spec.rb +35 -25
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +14 -26
- data/spec/mongoid/relations/synchronization_spec.rb +48 -2
- data/spec/mongoid/relations/targets/enumerable_spec.rb +108 -0
- data/spec/mongoid/relations/touchable_spec.rb +40 -0
- data/spec/mongoid/reloadable_spec.rb +51 -0
- data/spec/mongoid/scopable_spec.rb +13 -0
- data/spec/mongoid/serializable_spec.rb +0 -50
- data/spec/mongoid/threaded_spec.rb +68 -0
- data/spec/mongoid/validatable/presence_spec.rb +1 -1
- data/spec/mongoid/validatable/uniqueness_spec.rb +18 -9
- data/spec/mongoid/validatable_spec.rb +16 -0
- data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
- data/spec/spec_helper.rb +101 -8
- data/spec/support/cluster_config.rb +158 -0
- data/spec/support/constraints.rb +101 -0
- data/spec/support/macros.rb +20 -0
- data/spec/support/session_registry.rb +50 -0
- data/spec/support/spec_config.rb +42 -0
- data.tar.gz.sig +0 -0
- metadata +163 -61
- metadata.gz.sig +0 -0
- data/lib/mongoid/clients/thread_options.rb +0 -19
- data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
- data/lib/mongoid/railties/document.rb +0 -12
- data/spec/mongoid/railties/document_spec.rb +0 -24
data/lib/mongoid/composable.rb
CHANGED
@@ -12,6 +12,7 @@ require "mongoid/scopable"
|
|
12
12
|
require "mongoid/serializable"
|
13
13
|
require "mongoid/shardable"
|
14
14
|
require "mongoid/stateful"
|
15
|
+
require "mongoid/cacheable"
|
15
16
|
require "mongoid/traversable"
|
16
17
|
require "mongoid/validatable"
|
17
18
|
|
@@ -32,7 +33,6 @@ module Mongoid
|
|
32
33
|
include ActiveModel::Model
|
33
34
|
include ActiveModel::ForbiddenAttributesProtection
|
34
35
|
include ActiveModel::Serializers::JSON
|
35
|
-
include ActiveModel::Serializers::Xml
|
36
36
|
include Atomic
|
37
37
|
include Changeable
|
38
38
|
include Clients
|
@@ -50,6 +50,7 @@ module Mongoid
|
|
50
50
|
include Serializable
|
51
51
|
include Shardable
|
52
52
|
include Stateful
|
53
|
+
include Cacheable
|
53
54
|
include Threaded::Lifecycle
|
54
55
|
include Traversable
|
55
56
|
include Validatable
|
@@ -74,16 +75,42 @@ module Mongoid
|
|
74
75
|
Scopable,
|
75
76
|
Serializable,
|
76
77
|
Clients,
|
78
|
+
Clients::Options,
|
77
79
|
Shardable,
|
78
80
|
Stateful,
|
81
|
+
Cacheable,
|
79
82
|
Threaded::Lifecycle,
|
80
83
|
Traversable,
|
81
84
|
Validatable,
|
82
85
|
Equality,
|
86
|
+
Relations::Synchronization,
|
87
|
+
Relations::Macros,
|
83
88
|
ActiveModel::Model,
|
84
89
|
ActiveModel::Validations
|
85
90
|
]
|
86
91
|
|
92
|
+
# These are methods names defined in included blocks that may conflict
|
93
|
+
# with user-defined relation or field names.
|
94
|
+
# They won't be in the list of Module.instance_methods on which the
|
95
|
+
# #prohibited_methods code below is dependent so we must track them
|
96
|
+
# separately.
|
97
|
+
#
|
98
|
+
# @return [ Array<Symbol> ] A list of reserved method names.
|
99
|
+
#
|
100
|
+
# @since 6.0.0
|
101
|
+
RESERVED_METHOD_NAMES = [ :fields,
|
102
|
+
:aliased_fields,
|
103
|
+
:localized_fields,
|
104
|
+
:index_specifications,
|
105
|
+
:shard_key_fields,
|
106
|
+
:nested_attributes,
|
107
|
+
:readonly_attributes,
|
108
|
+
:storage_options,
|
109
|
+
:cascades,
|
110
|
+
:cyclic,
|
111
|
+
:cache_timestamp_format
|
112
|
+
]
|
113
|
+
|
87
114
|
class << self
|
88
115
|
|
89
116
|
# Get a list of methods that would be a bad idea to define as field names
|
@@ -98,7 +125,7 @@ module Mongoid
|
|
98
125
|
def prohibited_methods
|
99
126
|
@prohibited_methods ||= MODULES.flat_map do |mod|
|
100
127
|
mod.instance_methods.map(&:to_sym)
|
101
|
-
end
|
128
|
+
end + RESERVED_METHOD_NAMES
|
102
129
|
end
|
103
130
|
end
|
104
131
|
end
|
data/lib/mongoid/config.rb
CHANGED
@@ -25,6 +25,7 @@ module Mongoid
|
|
25
25
|
option :use_activesupport_time_zone, default: true
|
26
26
|
option :use_utc, default: false
|
27
27
|
option :log_level, default: :info
|
28
|
+
option :belongs_to_required_by_default, default: true
|
28
29
|
option :app_name, default: nil
|
29
30
|
|
30
31
|
# Has Mongoid been configured? This is checking that at least a valid
|
@@ -23,7 +23,7 @@ module Mongoid
|
|
23
23
|
#
|
24
24
|
# @since 3.0.0
|
25
25
|
def aggregates(field)
|
26
|
-
result = collection.find.aggregate(pipeline(field)).to_a
|
26
|
+
result = collection.find.aggregate(pipeline(field), session: _session).to_a
|
27
27
|
if result.empty?
|
28
28
|
{ "count" => 0, "sum" => nil, "avg" => nil, "min" => nil, "max" => nil }
|
29
29
|
else
|
@@ -109,16 +109,16 @@ module Mongoid
|
|
109
109
|
# Perform an atomic $push/$each operation on the matching documents.
|
110
110
|
#
|
111
111
|
# @example Push the values to the matching docs.
|
112
|
-
# context.
|
112
|
+
# context.push_all(members: [ "Alan", "Fletch" ])
|
113
113
|
#
|
114
114
|
# @param [ Hash ] pushes The operations.
|
115
115
|
#
|
116
116
|
# @return [ nil ] Nil.
|
117
117
|
#
|
118
|
-
# @since
|
119
|
-
def
|
118
|
+
# @since 3.0.0
|
119
|
+
def push_all(pushes)
|
120
120
|
push_each_updates = collect_operations(pushes).each.inject({}) do |ops, (field, elements)|
|
121
|
-
ops.merge!(field => {
|
121
|
+
ops.merge!(field => {'$each' => elements})
|
122
122
|
end
|
123
123
|
view.update_many("$push" => push_each_updates)
|
124
124
|
end
|
@@ -165,13 +165,13 @@ module Mongoid
|
|
165
165
|
def raw
|
166
166
|
validate_out!
|
167
167
|
cmd = command
|
168
|
-
opts = { read: cmd.delete(:read)
|
169
|
-
@map_reduce.database.command(cmd, opts || {}).first
|
168
|
+
opts = { read: cmd.delete(:read) } if cmd[:read]
|
169
|
+
@map_reduce.database.command(cmd, (opts || {}).merge(session: _session)).first
|
170
170
|
end
|
171
171
|
alias :results :raw
|
172
172
|
|
173
173
|
# Execute the map/reduce, returning the raw output.
|
174
|
-
# Useful when you don't care about map/reduce's
|
174
|
+
# Useful when you don't care about map/reduce's output.
|
175
175
|
#
|
176
176
|
# @example Run the map reduce
|
177
177
|
# map_reduce.execute
|
@@ -249,6 +249,10 @@ module Mongoid
|
|
249
249
|
def validate_out!
|
250
250
|
raise Errors::NoMapReduceOutput.new({}) unless @map_reduce.out
|
251
251
|
end
|
252
|
+
|
253
|
+
def _session
|
254
|
+
criteria.send(:_session)
|
255
|
+
end
|
252
256
|
end
|
253
257
|
end
|
254
258
|
end
|
@@ -44,11 +44,12 @@ module Mongoid
|
|
44
44
|
deleted = count
|
45
45
|
removed = map do |doc|
|
46
46
|
prepare_remove(doc)
|
47
|
-
doc.
|
47
|
+
doc.send(:as_attributes)
|
48
48
|
end
|
49
49
|
unless removed.empty?
|
50
50
|
collection.find(selector).update_one(
|
51
|
-
positionally(selector, "$pullAll" => { path => removed })
|
51
|
+
positionally(selector, "$pullAll" => { path => removed }),
|
52
|
+
session: _session
|
52
53
|
)
|
53
54
|
end
|
54
55
|
deleted
|
@@ -148,7 +149,7 @@ module Mongoid
|
|
148
149
|
@documents = criteria.documents.select do |doc|
|
149
150
|
@root ||= doc._root
|
150
151
|
@collection ||= root.collection
|
151
|
-
doc.
|
152
|
+
doc._matches?(criteria.selector)
|
152
153
|
end
|
153
154
|
apply_sorting
|
154
155
|
apply_options
|
@@ -303,7 +304,7 @@ module Mongoid
|
|
303
304
|
updates["$set"].merge!(doc.atomic_updates["$set"] || {})
|
304
305
|
doc.move_changes
|
305
306
|
end
|
306
|
-
collection.find(selector).update_one(updates) unless updates["$set"].empty?
|
307
|
+
collection.find(selector).update_one(updates, session: _session) unless updates["$set"].empty?
|
307
308
|
end
|
308
309
|
|
309
310
|
# Get the limiting value.
|
@@ -444,6 +445,10 @@ module Mongoid
|
|
444
445
|
doc._parent.remove_child(doc)
|
445
446
|
doc.destroyed = true
|
446
447
|
end
|
448
|
+
|
449
|
+
def _session
|
450
|
+
@criteria.send(:_session)
|
451
|
+
end
|
447
452
|
end
|
448
453
|
end
|
449
454
|
end
|
@@ -24,6 +24,7 @@ module Mongoid
|
|
24
24
|
:sort,
|
25
25
|
:batch_size,
|
26
26
|
:max_scan,
|
27
|
+
:max_time_ms,
|
27
28
|
:snapshot,
|
28
29
|
:comment,
|
29
30
|
:read,
|
@@ -94,7 +95,8 @@ module Mongoid
|
|
94
95
|
def destroy
|
95
96
|
each.inject(0) do |count, doc|
|
96
97
|
doc.destroy
|
97
|
-
count += 1
|
98
|
+
count += 1 if acknowledged_write?
|
99
|
+
count
|
98
100
|
end
|
99
101
|
end
|
100
102
|
alias :destroy_all :destroy
|
@@ -110,7 +112,9 @@ module Mongoid
|
|
110
112
|
#
|
111
113
|
# @since 3.0.0
|
112
114
|
def distinct(field)
|
113
|
-
view.distinct(klass.database_field_name(field))
|
115
|
+
view.distinct(klass.database_field_name(field)).map do |value|
|
116
|
+
value.class.demongoize(value)
|
117
|
+
end
|
114
118
|
end
|
115
119
|
|
116
120
|
# Iterate over the context. If provided a block, yield to a Mongoid
|
@@ -233,21 +237,33 @@ module Mongoid
|
|
233
237
|
# @example Get the first document.
|
234
238
|
# context.first
|
235
239
|
#
|
236
|
-
# @note
|
237
|
-
#
|
238
|
-
#
|
239
|
-
#
|
240
|
-
#
|
240
|
+
# @note Automatically adding a sort on _id when no other sort is
|
241
|
+
# defined on the criteria has the potential to cause bad performance issues.
|
242
|
+
# If you experience unexpected poor performance when using #first or #last
|
243
|
+
# and have no sort defined on the criteria, use the option { id_sort: :none }.
|
244
|
+
# Be aware that #first/#last won't guarantee order in this case.
|
245
|
+
#
|
246
|
+
# @param [ Hash ] opts The options for the query returning the first document.
|
247
|
+
#
|
248
|
+
# @option opts [ :none ] :id_sort Don't apply a sort on _id if no other sort
|
249
|
+
# is defined on the criteria.
|
241
250
|
#
|
242
251
|
# @return [ Document ] The first document.
|
243
252
|
#
|
244
253
|
# @since 3.0.0
|
245
|
-
def first
|
254
|
+
def first(opts = {})
|
246
255
|
return documents.first if cached? && cache_loaded?
|
247
256
|
try_cache(:first) do
|
248
|
-
if
|
249
|
-
|
250
|
-
|
257
|
+
if sort = view.sort || ({ _id: 1 } unless opts[:id_sort] == :none)
|
258
|
+
if raw_doc = view.sort(sort).limit(-1).first
|
259
|
+
doc = Factory.from_db(klass, raw_doc, criteria.options[:fields])
|
260
|
+
eager_load([doc]).first
|
261
|
+
end
|
262
|
+
else
|
263
|
+
if raw_doc = view.limit(-1).first
|
264
|
+
doc = Factory.from_db(klass, raw_doc, criteria.options[:fields])
|
265
|
+
eager_load([doc]).first
|
266
|
+
end
|
251
267
|
end
|
252
268
|
end
|
253
269
|
end
|
@@ -323,9 +339,9 @@ module Mongoid
|
|
323
339
|
# @since 3.0.0
|
324
340
|
def initialize(criteria)
|
325
341
|
@criteria, @klass, @cache = criteria, criteria.klass, criteria.options[:cache]
|
326
|
-
@collection = @klass.
|
342
|
+
@collection = @klass.collection
|
327
343
|
criteria.send(:merge_type_selection)
|
328
|
-
@view = collection.find(criteria.selector)
|
344
|
+
@view = collection.find(criteria.selector, session: _session)
|
329
345
|
apply_options
|
330
346
|
end
|
331
347
|
|
@@ -336,18 +352,21 @@ module Mongoid
|
|
336
352
|
# @example Get the last document.
|
337
353
|
# context.last
|
338
354
|
#
|
339
|
-
# @note
|
340
|
-
#
|
341
|
-
#
|
342
|
-
#
|
343
|
-
#
|
355
|
+
# @note Automatically adding a sort on _id when no other sort is
|
356
|
+
# defined on the criteria has the potential to cause bad performance issues.
|
357
|
+
# If you experience unexpected poor performance when using #first or #last
|
358
|
+
# and have no sort defined on the criteria, use the option { id_sort: :none }.
|
359
|
+
# Be aware that #first/#last won't guarantee order in this case.
|
360
|
+
#
|
361
|
+
# @param [ Hash ] opts The options for the query returning the first document.
|
344
362
|
#
|
345
|
-
# @
|
363
|
+
# @option opts [ :none ] :id_sort Don't apply a sort on _id if no other sort
|
364
|
+
# is defined on the criteria.
|
346
365
|
#
|
347
366
|
# @since 3.0.0
|
348
|
-
def last
|
367
|
+
def last(opts = {})
|
349
368
|
try_cache(:last) do
|
350
|
-
with_inverse_sorting do
|
369
|
+
with_inverse_sorting(opts) do
|
351
370
|
if raw_doc = view.limit(-1).first
|
352
371
|
doc = Factory.from_db(klass, raw_doc, criteria.options[:fields])
|
353
372
|
eager_load([doc]).first
|
@@ -468,12 +487,16 @@ module Mongoid
|
|
468
487
|
# context.update({ "$set" => { name: "Smiths" }})
|
469
488
|
#
|
470
489
|
# @param [ Hash ] attributes The new attributes for the document.
|
490
|
+
# @param [ Hash ] opts The update operation options.
|
491
|
+
#
|
492
|
+
# @option opts [ Array ] :array_filters A set of filters specifying to which array elements
|
493
|
+
# an update should apply.
|
471
494
|
#
|
472
495
|
# @return [ nil, false ] False if no attributes were provided.
|
473
496
|
#
|
474
497
|
# @since 3.0.0
|
475
|
-
def update(attributes = nil)
|
476
|
-
update_documents(attributes)
|
498
|
+
def update(attributes = nil, opts = {})
|
499
|
+
update_documents(attributes, :update_one, opts)
|
477
500
|
end
|
478
501
|
|
479
502
|
# Update all the matching documents atomically.
|
@@ -482,12 +505,16 @@ module Mongoid
|
|
482
505
|
# context.update_all({ "$set" => { name: "Smiths" }})
|
483
506
|
#
|
484
507
|
# @param [ Hash ] attributes The new attributes for each document.
|
508
|
+
# @param [ Hash ] opts The update operation options.
|
509
|
+
#
|
510
|
+
# @option opts [ Array ] :array_filters A set of filters specifying to which array elements
|
511
|
+
# an update should apply.
|
485
512
|
#
|
486
513
|
# @return [ nil, false ] False if no attributes were provided.
|
487
514
|
#
|
488
515
|
# @since 3.0.0
|
489
|
-
def update_all(attributes = nil)
|
490
|
-
update_documents(attributes, :update_many)
|
516
|
+
def update_all(attributes = nil, opts = {})
|
517
|
+
update_documents(attributes, :update_many, opts)
|
491
518
|
end
|
492
519
|
|
493
520
|
private
|
@@ -523,10 +550,10 @@ module Mongoid
|
|
523
550
|
# @return [ true, false ] If the update succeeded.
|
524
551
|
#
|
525
552
|
# @since 3.0.4
|
526
|
-
def update_documents(attributes, method = :update_one)
|
553
|
+
def update_documents(attributes, method = :update_one, opts = {})
|
527
554
|
return false unless attributes
|
528
555
|
attributes = Hash[attributes.map { |k, v| [klass.database_field_name(k.to_s), v] }]
|
529
|
-
view.send(method, attributes.__consolidate__(klass))
|
556
|
+
view.send(method, attributes.__consolidate__(klass), opts)
|
530
557
|
end
|
531
558
|
|
532
559
|
# Apply the field limitations.
|
@@ -583,10 +610,10 @@ module Mongoid
|
|
583
610
|
# context.with_inverse_sorting
|
584
611
|
#
|
585
612
|
# @since 3.0.0
|
586
|
-
def with_inverse_sorting
|
613
|
+
def with_inverse_sorting(opts = {})
|
587
614
|
begin
|
588
|
-
if
|
589
|
-
@view = view.sort(Hash[
|
615
|
+
if sort = criteria.options[:sort] || ( { _id: 1 } unless opts[:id_sort] == :none )
|
616
|
+
@view = view.sort(Hash[sort.map{|k, v| [k, -1*v]}])
|
590
617
|
end
|
591
618
|
yield
|
592
619
|
ensure
|
@@ -678,6 +705,14 @@ module Mongoid
|
|
678
705
|
yield(doc)
|
679
706
|
documents.push(doc) if cacheable?
|
680
707
|
end
|
708
|
+
|
709
|
+
def _session
|
710
|
+
@criteria.send(:_session)
|
711
|
+
end
|
712
|
+
|
713
|
+
def acknowledged_write?
|
714
|
+
collection.write_concern.nil? || collection.write_concern.acknowledged?
|
715
|
+
end
|
681
716
|
end
|
682
717
|
end
|
683
718
|
end
|
@@ -21,6 +21,18 @@ module Mongoid
|
|
21
21
|
other.is_a?(None)
|
22
22
|
end
|
23
23
|
|
24
|
+
# Allow distinct for null context.
|
25
|
+
#
|
26
|
+
# @example Get the distinct values.
|
27
|
+
# context.distinct(:name)
|
28
|
+
#
|
29
|
+
# @param [ String, Symbol ] field the name of the field.
|
30
|
+
#
|
31
|
+
# @return [ Array ] Empty Array
|
32
|
+
def distinct(field)
|
33
|
+
[]
|
34
|
+
end
|
35
|
+
|
24
36
|
# Iterate over the null context. There are no documents to iterate over
|
25
37
|
# in this case.
|
26
38
|
#
|
data/lib/mongoid/copyable.rb
CHANGED
@@ -20,11 +20,18 @@ module Mongoid
|
|
20
20
|
# _id and id field in the document would cause problems with Mongoid
|
21
21
|
# elsewhere.
|
22
22
|
attrs = clone_document.except("_id", "id")
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
dynamic_attrs = {}
|
24
|
+
attrs.reject! do |attr_name, value|
|
25
|
+
dynamic_attrs.merge!(attr_name => value) unless self.attribute_names.include?(attr_name)
|
26
|
+
end
|
27
|
+
self.class.new(attrs).tap do |object|
|
28
|
+
dynamic_attrs.each do |attr_name, value|
|
29
|
+
if object.respond_to?("#{attr_name}=")
|
30
|
+
object.send("#{attr_name}=", value)
|
31
|
+
else
|
32
|
+
object.attributes[attr_name] = value
|
33
|
+
end
|
34
|
+
end
|
28
35
|
end
|
29
36
|
end
|
30
37
|
alias :dup :clone
|
@@ -40,7 +47,7 @@ module Mongoid
|
|
40
47
|
#
|
41
48
|
# @since 3.0.22
|
42
49
|
def clone_document
|
43
|
-
attrs =
|
50
|
+
attrs = as_attributes.__deep_copy__
|
44
51
|
process_localized_attributes(self, attrs)
|
45
52
|
attrs
|
46
53
|
end
|
@@ -27,8 +27,8 @@ module Mongoid
|
|
27
27
|
def marshal_load(data)
|
28
28
|
@scoping_options, raw_selector, raw_options = data.pop(3)
|
29
29
|
@klass, @driver, @inclusions, @documents, @strategy, @negating = data
|
30
|
-
@selector = load_hash(
|
31
|
-
@options = load_hash(
|
30
|
+
@selector = load_hash(Queryable::Selector, raw_selector)
|
31
|
+
@options = load_hash(Queryable::Options, raw_options)
|
32
32
|
end
|
33
33
|
|
34
34
|
private
|
@@ -3,6 +3,10 @@ module Mongoid
|
|
3
3
|
class Criteria
|
4
4
|
module Modifiable
|
5
5
|
|
6
|
+
# @attribute [r] create_attrs Additional attributes to add to the Document upon creation.
|
7
|
+
# @api private
|
8
|
+
attr_reader :create_attrs
|
9
|
+
|
6
10
|
# Build a document given the selector and return it.
|
7
11
|
# Complex criteria, such as $in and $or operations will get ignored.
|
8
12
|
#
|
@@ -57,6 +61,9 @@ module Mongoid
|
|
57
61
|
|
58
62
|
# Define attributes with which new documents will be created.
|
59
63
|
#
|
64
|
+
# Note that if `find_or_create_by` is called after this in a method chain, the attributes in
|
65
|
+
# the query will override those from this method.
|
66
|
+
#
|
60
67
|
# @example Define attributes to be used when a new document is created.
|
61
68
|
# Person.create_with(job: 'Engineer').find_or_create_by(employer: 'MongoDB')
|
62
69
|
#
|
@@ -64,7 +71,9 @@ module Mongoid
|
|
64
71
|
#
|
65
72
|
# @since 5.1.0
|
66
73
|
def create_with(attrs = {})
|
67
|
-
|
74
|
+
tap do
|
75
|
+
(@create_attrs ||= {}).merge!(attrs)
|
76
|
+
end
|
68
77
|
end
|
69
78
|
|
70
79
|
# Find the first +Document+ given the conditions, or creates a new document
|
@@ -172,8 +181,9 @@ module Mongoid
|
|
172
181
|
#
|
173
182
|
# @since 3.0.0
|
174
183
|
def create_document(method, attrs = nil, &block)
|
175
|
-
|
176
|
-
|
184
|
+
attrs = (create_attrs || {}).merge(attrs || {})
|
185
|
+
attributes = selector.reduce(attrs) do |hash, (key, value)|
|
186
|
+
unless invalid_key?(hash, key) || invalid_embedded_doc?(value)
|
177
187
|
hash[key] = value
|
178
188
|
end
|
179
189
|
hash
|
@@ -216,6 +226,22 @@ module Mongoid
|
|
216
226
|
def first_or(method, attrs = {}, &block)
|
217
227
|
first || create_document(method, attrs, &block)
|
218
228
|
end
|
229
|
+
|
230
|
+
private
|
231
|
+
|
232
|
+
def invalid_key?(hash, key)
|
233
|
+
# @todo Change this to BSON::String::ILLEGAL_KEY when ruby driver 2.3.0 is
|
234
|
+
# released and mongoid is updated to depend on driver >= 2.3.0
|
235
|
+
key.to_s =~ Mongoid::Document::ILLEGAL_KEY || hash.key?(key.to_sym) || hash.key?(key)
|
236
|
+
end
|
237
|
+
|
238
|
+
def invalid_embedded_doc?(value)
|
239
|
+
# @todo Change this to BSON::String::ILLEGAL_KEY when ruby driver 2.3.0 is
|
240
|
+
# released and mongoid is updated to depend on driver >= 2.3.0
|
241
|
+
value.is_a?(Hash) && value.any? do |key, v|
|
242
|
+
key.to_s =~ Mongoid::Document::ILLEGAL_KEY || invalid_embedded_doc?(v)
|
243
|
+
end
|
244
|
+
end
|
219
245
|
end
|
220
246
|
end
|
221
247
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
class Criteria
|
4
|
+
|
5
|
+
# Module containing functionality for getting options on a Criteria object.
|
6
|
+
#
|
7
|
+
# @since 6.0.0
|
8
|
+
module Options
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def persistence_context
|
13
|
+
klass.persistence_context
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_persistence_context(options)
|
17
|
+
PersistenceContext.set(klass, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def clear_persistence_context(original_cluster)
|
21
|
+
PersistenceContext.clear(klass, original_cluster)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
class Criteria
|
4
|
+
module Queryable
|
5
|
+
|
6
|
+
# Provides a DSL around crafting aggregation framework commands.
|
7
|
+
#
|
8
|
+
# @since 2.0.0
|
9
|
+
module Aggregable
|
10
|
+
extend Macroable
|
11
|
+
|
12
|
+
# @attribute [r] pipeline The aggregation pipeline.
|
13
|
+
attr_reader :pipeline
|
14
|
+
|
15
|
+
# @attribute [rw] aggregating Flag for whether or not we are aggregating.
|
16
|
+
attr_writer :aggregating
|
17
|
+
|
18
|
+
# Has the aggregable enter an aggregation state. Ie, are only aggregation
|
19
|
+
# operations allowed at this point on.
|
20
|
+
#
|
21
|
+
# @example Is the aggregable aggregating?
|
22
|
+
# aggregable.aggregating?
|
23
|
+
#
|
24
|
+
# @return [ true, false ] If the aggregable is aggregating.
|
25
|
+
#
|
26
|
+
# @since 2.0.0
|
27
|
+
def aggregating?
|
28
|
+
!!@aggregating
|
29
|
+
end
|
30
|
+
|
31
|
+
# Add a group ($group) operation to the aggregation pipeline.
|
32
|
+
#
|
33
|
+
# @example Add a group operation being verbose.
|
34
|
+
# aggregable.group(count: { "$sum" => 1 }, max: { "$max" => "likes" })
|
35
|
+
#
|
36
|
+
# @example Add a group operation using symbol shortcuts.
|
37
|
+
# aggregable.group(:count.sum => 1, :max.max => "likes")
|
38
|
+
#
|
39
|
+
# @param [ Hash ] operation The group operation.
|
40
|
+
#
|
41
|
+
# @return [ Aggregable ] The aggregable.
|
42
|
+
#
|
43
|
+
# @since 2.0.0
|
44
|
+
def group(operation)
|
45
|
+
aggregation(operation) do |pipeline|
|
46
|
+
pipeline.group(operation)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
key :avg, :override, "$avg"
|
50
|
+
key :max, :override, "$max"
|
51
|
+
key :min, :override, "$min"
|
52
|
+
key :sum, :override, "$sum"
|
53
|
+
key :last, :override, "$last"
|
54
|
+
key :push, :override, "$push"
|
55
|
+
key :first, :override, "$first"
|
56
|
+
key :add_to_set, :override, "$addToSet"
|
57
|
+
|
58
|
+
# Add a projection ($project) to the aggregation pipeline.
|
59
|
+
#
|
60
|
+
# @example Add a projection to the pipeline.
|
61
|
+
# aggregable.project(author: 1, name: 0)
|
62
|
+
#
|
63
|
+
# @param [ Hash ] operation The projection to make.
|
64
|
+
#
|
65
|
+
# @return [ Aggregable ] The aggregable.
|
66
|
+
#
|
67
|
+
# @since 2.0.0
|
68
|
+
def project(operation = nil)
|
69
|
+
aggregation(operation) do |pipeline|
|
70
|
+
pipeline.project(operation)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Add an unwind ($unwind) to the aggregation pipeline.
|
75
|
+
#
|
76
|
+
# @example Add an unwind to the pipeline.
|
77
|
+
# aggregable.unwind(:field)
|
78
|
+
#
|
79
|
+
# @param [ String, Symbol ] field The name of the field to unwind.
|
80
|
+
#
|
81
|
+
# @return [ Aggregable ] The aggregable.
|
82
|
+
#
|
83
|
+
# @since 2.0.0
|
84
|
+
def unwind(field)
|
85
|
+
aggregation(field) do |pipeline|
|
86
|
+
pipeline.unwind(field)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# Add the aggregation operation.
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
#
|
96
|
+
# @example Aggregate on the operation.
|
97
|
+
# aggregation(operation) do |pipeline|
|
98
|
+
# pipeline.push("$project" => operation)
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# @param [ Hash ] operation The operation for the pipeline.
|
102
|
+
#
|
103
|
+
# @return [ Aggregable ] The cloned aggregable.
|
104
|
+
#
|
105
|
+
# @since 2.0.0
|
106
|
+
def aggregation(operation)
|
107
|
+
return self unless operation
|
108
|
+
clone.tap do |query|
|
109
|
+
unless aggregating?
|
110
|
+
query.pipeline.concat(query.selector.to_pipeline)
|
111
|
+
query.pipeline.concat(query.options.to_pipeline)
|
112
|
+
query.aggregating = true
|
113
|
+
end
|
114
|
+
yield(query.pipeline)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|