-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: None
-
Component/s: Associations, Performance
After updating to Mongoid 8 from 7.5 we noticed 2 problems with `belongs_to` associations:
- performance issues
- validation issues
tl;dr - Mongoid 8 started to validate full chain of dependent objects.
Here is simplified example (our real app scenario is way more complex):
# MODELS class A include Mongoid::Document include Mongoid::Timestamps belongs_to :b end class B include Mongoid::Document include Mongoid::Timestamps has_one :a belongs_to :c end class C include Mongoid::Document include Mongoid::Timestamps has_one :b embeds_many :embs end class Emb include Mongoid::Document include Mongoid::Timestamps embedded_in :c belongs_to :d end class D include Mongoid::Document include Mongoid::Timestamps has_one :emb field :name, type: String validates :name, presence: true end
# SETUP ds = 20.times.map { D.create!(name: 'abc') } embs = ds.map { |d| Emb.new(d:) } c = C.create!(embs:) b = B.create!(c:)
Performance issue
# TEST SCENARIO b = B.last a = A.create!(b:)
In Mongoid 7.5 you'll see only 2 mongo queries:
| STARTED | {"find"=>"bs", ... | STARTED | {"insert"=>"as", ...
However in Mongoid 8.x it fetches the full chain of dependent objects which basically makes create action X times slower (depending on number of associations):
| STARTED | {"find"=>"bs", ... | STARTED | {"find"=>"cs", ... | STARTED | {"find"=>"ds", ... x20 | STARTED | {"insert"=>"as", ...
This approach looks incorrect. It's ok to validate 1st level associations but validating the whole chain could lead to a problems. Besides performance issues there is a chance that some record deep below has some validation errors which will lead to impossibility to save.
Validation issue
This works in 7.5, but doesn't work in 8:
b = B.last b.c.embs.first.d.set(name: nil) # make record invalid exit b = B.last a = A.create!(b:)
Mongoid 8 will show:
/Users/xxx/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/mongoid-8.1.3/lib/mongoid/persistable.rb:125:in `fail_due_to_validation!': (Mongoid::Errors::Validations) message: Validation of A failed. summary: The following errors were found: B is invalid resolution: Try persisting the document with valid data or remove the validations.
While Mongoid 7.5 will correctly create a record.
It's a pretty common scenario when some record which was created N years ago is invalid. And that's fine. We are not touching or updating it. But this creates issues in places where you don't expect them. Certain parts of application start to trigger validation errors which are not related to the source of call.
And obviously this happens when updating record and by just calling valid?.
Additional notes:
- Mongoid.belongs_to_required_by_default is true
- all belongs_to assiciations are required and we can't change any of these options.
- is caused by
-
MONGOID-4160 Don't persist document if associated document is invalid with optional: false
- Closed
- is duplicated by
-
MONGOID-5740 Investigate performance regression in Mongoid 8
- Closed
-
MONGOID-5635 default value of belongs_to_required_by_default causes performance issues
- Closed
- is related to
-
MONGOID-5744 Release Mongoid 8.0.8, 8.1.5
- Closed
- related to
-
MONGOID-5635 default value of belongs_to_required_by_default causes performance issues
- Closed