title: Django query omitting expected results
body: <p>I must perform a query on a large database with a somewhat intricate modeling, which I will try to abridge below:</p>
  
  <pre><code>class ScreeningItem(models.Model):
      # other fields
      receivedItem = models.OneToOneField(ReceivedItem, null=True, on_delete=models.SET_NULL)
  
  class ReceivedItem(models.Model):
      # other fields
      dossier = models.ForeignKey(Dossier, null=True, on_delete=models.SET_NULL)
  
  class Dossier(models.Model):
      # other fields
      subjects = models.ManyToManyField('SubjectTypes', through='Subjects',
                                        through_fields=('dossier', 'subjectType'))
  
  class Subject(models.Model):
      main = models.BooleanField(null=True)
      dossier = models.ForeignKey(Dossier, null=True, on_delete=models.SET_NULL)
      subjectType =  models.ForeignKey(SubjectType, null=True, on_delete=models.SET_NULL)
  
  class SubjectType(models.Model):
      # other fields
      name = models.CharField(max_length=255, null=True, blank=True)
      parent = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
  </code></pre>
  
  <p>Now, the problem is that I must find in <code>ScreeningItem</code> table items when the far, far away related field <code>SubjectType.name</code> contains specific words. No, worse. As you can see below, there's a parent-child self reference in that model, and I must look for those specific words in the related <code>SujectType</code>, its parent, and its grandparent, in case they exist.</p>
  
  <p>My attempt:</p>
  
  <pre><code>exp = 'something'
  queryset = ScreeningItem.objects.filter(
      Q(receivedItem__dossier__subjects__subjecttype__name__iregex=exp) |     
      Q(receivedItem__dossier__subjects__subjecttype__parent__name__iregex=exp) |     
      Q(receivedItem__dossier__subjects__subjecttype__parent__parent__name__iregex=exp))     
  </code></pre>
  
  <p>However, when I received a number of records much below I was expecting, I checked the database and discovered, for my astonishment, that there were many <code>ScreeningItem</code> which had a <code>ReceivedItem</code> which had a <code>Dossier</code> which was related to <code>SubjectTypes</code> which had the word I was searching for. </p>
  
  <p>Unfortunately, I'm not allowed to disclose the content here. So I wrote the test routine below:</p>
  
  <pre><code>def test():
      exp = 'something'  # valid and equal both for Python and MySQL regular expression engines
      re_exp = re.compile(exp, re.IGNORECASE)
      queryset_1 = ScreeningItem.objects.filter(
          Q(receivedItem__dossier__subjects__subjecttype__name__iregex=exp) |     
          Q(receivedItem__dossier__subjects__subjecttype__parent__name__iregex=exp) |     
          Q(receivedItem__dossier__subjects__subjecttype__parent__parent__name__iregex=exp))     
      set_1 = set(queryset_1.values_list('id', flat=True))
      print(len(set_1))
  
      queryset_2 = GnomoItemTriagem.objects.filter(receivedItem__dossier__isnull=False)
      set_2a = set()
      set_2b = set()
      for item in queryset_2:
          subjects = item.receivedItem.dossier.subjects
          if subjects.filter(
                  Q(name__iregex=exp) |
                  Q(parent__name__iregex=exp) |
                  Q(parent__parent__name__iregex=exp)).count() &gt; 0:
              set_2a.add(item.id)
  
          for subject in subjects.all():
              if re_exp.findall(subject.name) or\
                  (subject.parent and re_exp.findall(subject.parent.name)) or \
                      (subject.parent and subject.parent.parent and re_exp.findall(subject.parent.parent.name)):
                  set_2b.add(item.id)
  
      print(len(set_2a))
      print(len(set_2b))
  </code></pre>
  
  <p>And then my results were</p>
  
  <pre><code>1596
  21223
  21223
  </code></pre>
  
  <p>So how should my 1st query be written in order to also return all the 21223 items required? What am I doing wrong?</p>