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

Existing `$and` clause in query is overwritten by `where` condition

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 7.4.0
    • Affects Version/s: 7.2.5, 7.1.11, 7.3.3
    • Component/s: Query
    • None
    • Minor Change

      When multiple conditions on the same field are given in separate method invocations, Mongoid uses `$and` to store the newer conditions, e.g.:

      irb(main):012:0>  Band.where(id: 1).and({year: {'$in' => [2020]}}, {year: {'$in' => [2021]}})
      => 
      #<Mongoid::Criteria
        selector: {"_id"=>1, "year"=>{"$in"=>[2020]}, "$and"=>[{"year"=>{"$in"=>[2021]}}]}
        options:  {}
        class:    Band
        embedded: false>
      

      Here, there are two conditions on `year` and they are combined with `$and`.

      When `where` is used and is given a field which already exists in the criteria with the same operator, and the criteria also already contains an `$and` clause, Mongoid uses `$and` to add the new condition from `where` but in doing so apparently clobbers the existing `$and` clause, as follows:

      irb(main):014:0>  Band.where(id: 1).and({year: {'$in' => [2020]}}, {year: {'$in' => [2021]}}).where(id: 2
      )
      => 
      #<Mongoid::Criteria
        selector: {"_id"=>1, "year"=>{"$in"=>[2020]}, "$and"=>[{"_id"=>2}]}
        options:  {}
        class:    Band
        embedded: false>
      

      --------------------------------

      Original report:

      I've met the problem that the later expression is overriding precedent other '$and' expressions if expressions are appeared in the specific oder like this:
       

      # this is OK
      Band.where(id: 1).where(id: 2).selector
      => {"_id"=>1, "$and"=>[{"_id"=>2}]}
      
      # this is also OK
      Band.and({year: {'$in' => [2020]}}, {year: {'$in' => [2020]}}).selector
      => {"year"=>{"$in"=>[2020]}, "$and"=>[{"year"=>{"$in"=>[2020]}}]}
      
      # But this is bad, I think
      Band.where(id: 1).and({year: {'$in' => [2020]}}, {year: {'$in' => [2020]}}).where(id: 2).selector
      => {"_id"=>1, "year"=>{"$in"=>[2020]}, "$and"=>[{"_id"=>2}]}
      

       

            Assignee:
            dmitry.rybakov@mongodb.com Dmitry Rybakov
            Reporter:
            pinarello.marvel@gmail.com 英雄 中野
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: