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

Protecting has and belongs to many relations from trying to pull against a null set of ids

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

      I'm having an issue in one of my projects pointed at mongoid master that I can't seem to reproduce in specs on Mongoid. It's a HABTM relationship for, say, Person and House. If I do this, it fails:

      # This fails with invalid query because Person.send(:house_ids) returns nil and Mongoid this call
      Person.create.destroy
      # update test.houses query: { $and: [ { _id: { $in: null } } ] } update: { $pull: { person_ids: ObjectId('502e76addd365a00a4000001') } } 
      

      Yet this passes and works without problems:

      p = Person.create
      p.house_ids
      # => []
      p.destroy
      

      I've been trying to repro unsuccessfully in the Mongoid specs for about an hour, but this patch fixes the issue.

      Also, there are a ton of unnecessary database queries happening on a #destroy. I tried to hunt those down but hit my timebox. Check out the Mongo log from a simple call to Person.create.destroy in the mongoid specs:

      > Fri Aug 17 12:54:42 [conn86] run command mongoid_test.$cmd { count: "posts", query:

      { person_id: ObjectId('502e7752dd365a4ca4000001') }

      }
      > Fri Aug 17 12:54:42 [conn86] command mongoid_test.$cmd command: { count: "posts", query:

      { person_id: ObjectId('502e7752dd365a4ca4000001') }

      } ntoreturn:1 reslen:58 0ms
      > Fri Aug 17 12:54:42 [conn86] remove mongoid_test.posts query:

      { person_id: ObjectId('502e7752dd365a4ca4000001') }

      0ms
      > Fri Aug 17 12:54:42 [conn86] update mongoid_test.preferences query: { $and: [ { _id: { $in: {} } } ] } update: { $pull:

      { person_ids: ObjectId('502e7752dd365a4ca4000001') }

      } 0ms
      > Fri Aug 17 12:54:42 [conn86] update mongoid_test.people query:

      { _id: ObjectId('502e7752dd365a4ca4000001') }

      update: { $set: { preference_ids: {} } } idhack:1 moved:1 0ms
      > Fri Aug 17 12:54:42 [conn86] query mongoid_test.cats ntoreturn:1 scanAndOrder:1 reslen:20 0ms
      Fri Aug 17 12:54:42 [conn86] query mongoid_test.homes ntoreturn:1 scanAndOrder:1 reslen:20 0ms
      > Fri Aug 17 12:54:42 [conn86] update mongoid_test.events query: { $and: [ { _id: { $in: {} } } ] } update: { $pull:

      { administrator_ids: ObjectId('502e7752dd365a4ca4000001') }

      } 0ms
      > Fri Aug 17 12:54:42 [conn86] update mongoid_test.people query:

      { _id: ObjectId('502e7752dd365a4ca4000001') }

      update: { $set: { administrated_event_ids: {} } } idhack:1 0ms
      > Fri Aug 17 12:54:42 [conn86] remove mongoid_test.people query:

      { _id: ObjectId('502e7752dd365a4ca4000001') }

      0ms

      As you can see, there are a lot of count() operations as well as a lot of pulls that run against a blank set (_id $in nothing). In the latter cases, you should only be pulling if there is a document on which to pull. I tried to find where that change would be, but alas could not in my timebox.

            Assignee:
            Unassigned Unassigned
            Reporter:
            jonhyman Jon Hyman
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved: