Django 查询省略预期结果
Django query omitting expected results
我必须在具有复杂建模的大型数据库上执行查询,我将在下面尝试对其进行删减:
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)
现在,问题是我必须在 ScreeningItem
table 项中找到很远的相关字段 SubjectType.name
包含特定单词的项目。不,更糟。正如您在下面看到的,该模型中有一个父子自引用,我必须在相关的 SujectType
、它的父代和它的祖父代中寻找那些特定的词,以防它们存在。
我的尝试:
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))
然而,当我收到的记录数量远低于我的预期时,我检查了数据库,令我惊讶的是,有许多 ScreeningItem
有一个 ReceivedItem
Dossier
与 SubjectTypes
相关,其中包含我正在搜索的词。
很遗憾,我不能在这里透露内容。所以我写了下面的测试例程:
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() > 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))
然后我的结果是
1596
21223
21223
那么我的第一个查询应该如何编写才能 return 需要的所有 21223 个项目?我做错了什么?
由于 subjects
是 SubjectType
的多对多字段,它已经 "lands" 在该模型中。您可以查询另一个 __subjecttype
的原因是因为它正在访问 "reverse".
中 parent
的 ForeignKey
您的查询应如下所示:
queryset = ScreeningItem.objects.filter(
Q(receivedItem__dossier<b>__subjects</b>__name__iregex=exp) |
Q(receivedItem__dossier<b>__subjects</b>__parent__name__iregex=exp) |
Q(receivedItem__dossier<b>__subjects</b>__parent__parent__name__iregex=exp)
)
之所以没有报错是因为你的parent
关系没有related_name
。所以这意味着 parent
关系的默认 related_name_query
是 subjecttype
。结果,您进行了一个查询,您在哪里寻找 ScreeningItem
with a receivedItem
with a dossier
with as SubjectType
a child SubjectType
有一个名称查询,或 that child 等的父级等。 child 部分因此出错了.
我必须在具有复杂建模的大型数据库上执行查询,我将在下面尝试对其进行删减:
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)
现在,问题是我必须在 ScreeningItem
table 项中找到很远的相关字段 SubjectType.name
包含特定单词的项目。不,更糟。正如您在下面看到的,该模型中有一个父子自引用,我必须在相关的 SujectType
、它的父代和它的祖父代中寻找那些特定的词,以防它们存在。
我的尝试:
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))
然而,当我收到的记录数量远低于我的预期时,我检查了数据库,令我惊讶的是,有许多 ScreeningItem
有一个 ReceivedItem
Dossier
与 SubjectTypes
相关,其中包含我正在搜索的词。
很遗憾,我不能在这里透露内容。所以我写了下面的测试例程:
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() > 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))
然后我的结果是
1596
21223
21223
那么我的第一个查询应该如何编写才能 return 需要的所有 21223 个项目?我做错了什么?
由于 subjects
是 SubjectType
的多对多字段,它已经 "lands" 在该模型中。您可以查询另一个 __subjecttype
的原因是因为它正在访问 "reverse".
parent
的 ForeignKey
您的查询应如下所示:
queryset = ScreeningItem.objects.filter(
Q(receivedItem__dossier<b>__subjects</b>__name__iregex=exp) |
Q(receivedItem__dossier<b>__subjects</b>__parent__name__iregex=exp) |
Q(receivedItem__dossier<b>__subjects</b>__parent__parent__name__iregex=exp)
)
之所以没有报错是因为你的parent
关系没有related_name
。所以这意味着 parent
关系的默认 related_name_query
是 subjecttype
。结果,您进行了一个查询,您在哪里寻找 ScreeningItem
with a receivedItem
with a dossier
with as SubjectType
a child SubjectType
有一个名称查询,或 that child 等的父级等。 child 部分因此出错了.