Details
-
Improvement
-
Status: Backlog
-
Minor - P4
-
Resolution: Unresolved
-
7.0.4
-
None
Description
In MongoDB 3.6, filtered positional update operator was added as described here: https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#update-nested-arrays-in-conjunction-with. This operator permits find-and-modify operations on nested arrays of embedded documents - specifically, it is free of the restriction of the positional update operator (https://docs.mongodb.com/manual/reference/operator/update/positional/) which only works with one level of nested arrays.
Mongoid should use the filtered positional update operator to solve the following reported problem:
This seems to have been fixed before but it doesn't use the positional operator when an embedded document has embedded documents.
require 'mongoid' |
Mongoid.connect_to 'embedded_positional_operators_test' |
class Team |
include Mongoid::Document
|
embeds_many :players |
field :name, type: String, default: '' |
end
|
class Player |
include Mongoid::Document
|
embeds_many :previous_teams |
embedded_in :team, inverse_of: :players |
field :name, type: String, default: '' |
end
|
class PreviousTeam |
include Mongoid::Document
|
embedded_in :player, inverse_of: :previous_teams |
field :name, type: String, default: '' |
field :year, type: String, default: '' |
end
|
Team.delete_all
|
Team.create!(name: 'Falcons') |
falcons_instance_1 = Team.first
|
falcons_instance_2 = Team.first
|
falcons_instance_1.players.create!(name: 'Vidur', previous_teams: [{name: 'Eagles', year: '2018'}]) |
falcons_instance_2.players.create!(name: 'Jonathon', previous_teams: [{name: 'Paaaaaanthers', year: '2018'}]) |
me = falcons_instance_2.players.find_by(name: 'Jonathon') |
# me.previous_teams.find_or_initialize_by(year: '2018').update(name: 'Panthers')
|
me.previous_teams.find_or_initialize_by(year: '2018').assign_attributes(name: 'Panthers') |
me.save
|
Team.first.players.each do |player| |
previous_teams = player.previous_teams.each.map(&:name).join(', ') |
puts "Player Name: #{player.name}, Previous Teams: #{previous_teams}" |
end |
So the expected print would be:
Player Name: Vidur, Previous Teams: Eagles
Player Name: Jonathon, Previous Teams: Panthers
but it returns:
Player Name: Vidur, Previous Teams: Panthers
Player Name: Jonathon, Previous Teams: Paaaaaanthers
it looks like the query being created is:
{ q: { _id: ObjectId('5db0a55728f9d506e57a336d'), players._id: ObjectId('5db0a55728f9d506e57a3370') }, u: { $set: { players.0.previous_teams.0.name: "Panthers" } }
|
And that first 0 should be the positional operator $.
I looked through the code and found it was being done here and in there I see it uses positional operator only when nesting 1 level deep. Looking at the commit that added that im guessing its needed when the embedded document with the same name?
Attachments
Issue Links
- related to
-
MONGOID-4172 Regression: positional operators not used to update embedded records
-
- Closed
-