Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-248

References stored_as array do not preserve order

    • Type: Icon: Task Task
    • Resolution: Done
    • 12_01_17
    • Affects Version/s: None
    • Component/s: None
    • Labels:

      I had a major bug in my app caused by the following issue: I had a class Foo with a field

      references_many :bars, :stored_as => :array

      Here's the thing: If I added multiple Bar}}s to a {{Foo, saved the Foo, then fetched it from the database again, the bars array wasn't in the order I expected. I eventually figure out that the root cause was that, although the bar_ids were in the right order, the query used to construct the bars field from those ids was not order-ensuring:

      MONGODB my_db['bars'].find({:_id=>{"$in"=>[BSON::ObjectID('4c5c4e12289c7d0e2b000009'), BSON::ObjectID('4c5c4e12289c7d0e2b00000c')]}}, {})

      This query will return the right bars, but can (and does) return them in a different order than ObjectID array would suggest. I think it goes without saying that someone who uses :stored_as => :array expects the association to have a consistent order.

      In order to ensure that order, I propose that every :stored_as => :array target class have an array index field added (for each parent), and that field be used for an order_by call appended to the any_in call in the query method defined in references_many_as_array.rb:

      def query
      @query ||= lambda

      { @klass.any_in(:_id => @parent.send(@foreign_key)) }

      end

      Until this change is implemented, I'll have to use inefficient post-retrieval sorting:

      sorted_bars = foo.bars.to_a.sort

      {|x,y| foo.bar_ids.index(x.id) <=> foo.bar_ids.index(y.id)}

            Assignee:
            Unassigned Unassigned
            Reporter:
            trevorburnham Trevor Burnham
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved: