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

Scope merge problem

    • Type: Icon: Task Task
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 5.0.1
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None

      I have following classes

      class Category
        include Mongoid::Document
        include Mongoid::Ancestry
        has_ancestry cache_depth: true
      end
      
      class Product
        include Mongoid::Document
        scope :active_expired,      -> { where(status: :approved, :expired_at.lte => DateTime.now) }       
        scope :children_of, -> (category) { where(:category_ids.in => category.subtree_ids.to_a) }
      end
      

      I don't remember when it happen, but combination of scopes :children_of and :active_expired started merged wrong.

      Here is what I call:

      Product.active_expired.children_of(Category.first)
      

      Here is what I get in response:

       #<Mongoid::Criteria
        selector: {"status"=>:approved, "expired_at"=>{"$lte"=>2015-07-10 10:02:59 UTC}, "category_ids"=>{"$in"=>[]}}
        options:  {}
        class:    Product
        embedded: false>
      

      Here is mongo logs look like:

      2015-07-10T10:03:00.932+0000 I QUERY    [conn3494] query xmarket-products-new-br.products query: { status: "approved", expired_at: { $lte: new Date(1436522579447) }, $or: [ { _id: ObjectId('546b557e69702d48bf000000') }, { ancestry: /^546b557e69702d48bf000000// }, { ancestry: "546b557e69702d48bf000000" } ] } planSummary: IXSCAN { status: 1, expired_at: 1 } ntoreturn:0 ntoskip:0 nscanned:128989 nscannedObjects:128989 keyUpdates:0 writeConflicts:0 numYields:1770 nreturned:0 reslen:20 locks:{} 1466ms
      

      When I do:

      Product.active_expired.merge Product.children_of(c)
      

      or

      Product.children_of(c).active_expired
      

      I get

      #<Mongoid::Criteria
        selector: {"status"=>:approved, "expired_at"=>{"$lte"=>2015-07-10 10:04:09 UTC}, "category_ids"=>{"$in"=>[<BSON::ObjectId:0x70147113954100 data=546b557e69702d48bf000000>, <BSON::ObjectId:0x70147113953220 data=546b5a8f69702d4bfb000000>, <BSON::ObjectId:0x70147114081780 data=54efabbb69702d69b41a0000>]}}
        options:  {}
        class:    Product
        embedded: false>
      

      Which is correct, expected and worked before.

      P.S.
      category.subtree_ids is mongoid ancestry methods which call any_of internally

      Code below have same problem, so when you have where in where inside scope it merged incorrectly.

      scope :children_of, -> (category) { where(:category_ids.in => Category.where(id: category.id).map(&:id)) }
      

            Assignee:
            dianna.hohensee@mongodb.com Dianna Hohensee (Inactive)
            Reporter:
            rkyrychuk rkyrychuk
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: