Aze*_*zer 5 python django django-models django-queryset python-3.x
我有一个名为的抽象模型类,PostType
并有一些从中派生的子模型。该模型如下所示:
class PostType(models.Model):
title = models.CharField(
max_length=255,
unique=True,
verbose_name='Title'
)
description = models.CharField(
max_length=255,
default='',
verbose_name='Description'
)
tags = models.ManyToManyField(
to=Tag,
blank=True,
verbose_name='Tags'
)
content = RichTextUploadingField(
default='',
verbose_name='Post Content'
)
class Meta:
abstract = True
Run Code Online (Sandbox Code Playgroud)
它有一个相关的标签模型,如下所示:
class Tag(models.Model):
name = models.CharField(
max_length=255,
verbose_name='Name',
unique=True
)
description = models.TextField(
verbose_name='Description',
default=''
)
Run Code Online (Sandbox Code Playgroud)
在我的一种观点中,我尝试使用 aSearchVector
并搜索多个字段来查询所有子类:
query = request.GET.get('s')
from django.contrib.postgres.search import SearchVector
get_qs_list = [model.objects.annotate(
search=SearchVector('title', 'description', 'content', 'tags__name')
).filter(search=query) for model in models.PostType.__subclasses__()]
Run Code Online (Sandbox Code Playgroud)
现在,搜索正在返回所有应有的结果。但是,由于某种原因,它会返回某些项目的重复结果。
'tags__name'
如果我从 中删除,问题似乎就会消失SearchVector
,但我不明白为什么。
我做错了什么,如果我不搜索相关领域,为什么它会起作用?
编辑:
Tag
我刚刚意识到,对于与该项目相关的每个项目,我都会得到重复的结果。因此,如果该项目具有三个标签,我将在搜索结果中获得该项目的三个副本。我仍然不明白为什么会发生这种情况,非常感谢您的建议!
我知道这个问题很老了,但我今天一直在努力解决一个非常类似的问题并找到了解决方案。如果你看一下搜索向量的定义:
search = SearchVector(
'title',
'description',
'content',
'tags__name',
)
Run Code Online (Sandbox Code Playgroud)
您可能会注意到,虽然title
、description
和content
是模型上的字段PostType
,但tags__name
指的是相关模型Tag
。在这种情况下,关系不是一对一的 - 可能有多个标签与某个 PostType 相关。如果具有多个标签的搜索结果与您的搜索“匹配”,那么您将获得完全相同的结果,而 Djangodistinct()
不会帮助您(至少不会以我所知道的任何方式)。
但是,由于您使用的是 postgres,因此您还可以利用另一个功能ArrayAgg。它允许您使用所有标签的聚合值来注释您的查询集,稍后使用就像它是 PostType 上的字段一样:
from django.contrib.postgres.aggregates import ArrayAgg
# 1. annotate with aggregated tag name values
queryset = queryset.annotate(
tags_names=ArrayAgg(
"tags__name",
distinct=True,
),
)
# 2. use the annotation in the SearchVector
search = SearchVector(
'title',
'description',
'content',
'tags_names', # <-- note: not `tags__name`
)
Run Code Online (Sandbox Code Playgroud)
对于每个现在PostType
只有一个tags_names
由聚合值组成tags__name
,因此换句话说 - 是相关标签名称的列表;SearchVector
现在可以像任何其他领域一样使用。
旁注:除此之外,为了获得更好的结果,您还应该检查是否search__icontains=query
.
from django.contrib.postgres.search import SearchVector
from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import Q
query = request.GET.get('s')
get_qs_list = [
model.objects.annotate(
tags_names=ArrayAgg("tags__name", distinct=True),
search=SearchVector(
'title',
'description',
'content',
'tags_names',
),
).filter(
Q(search=query) | Q(search__icontains=query)
) for model in models.PostType.__subclasses__()
]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
443 次 |
最近记录: |