mirror of
https://github.com/suitenumerique/docs.git
synced 2026-09-13 05:07:52 +02:00
⚡️(backend) improve DocumentViewset.get_queryset
The filtering made in the DocumentViewset.get_queryset method is not optimal and lead to a full scan of the Document table. The heavy part is on the filtering on what the user can access between the accesses and the link traces. To have better performance we make an union operation of both document_id list and the filter the id on this list. Postgresql will use the index on the id column.
This commit is contained in:
@@ -581,22 +581,27 @@ class DocumentViewSet(
|
||||
queryset = queryset.filter(ancestors_deleted_at__isnull=True)
|
||||
|
||||
# Filter documents to which the current user has access...
|
||||
access_documents_ids = models.DocumentAccess.objects.filter(
|
||||
db.Q(user=user) | db.Q(team__in=user.teams)
|
||||
).values_list("document_id", flat=True)
|
||||
access_documents_ids = (
|
||||
models.DocumentAccess.objects.filter(
|
||||
db.Q(user=user) | db.Q(team__in=user.teams)
|
||||
)
|
||||
.order_by()
|
||||
.values_list("document_id", flat=True)
|
||||
)
|
||||
|
||||
# ...or that were previously accessed and are not restricted
|
||||
traced_documents_ids = models.LinkTrace.objects.filter(user=user).values_list(
|
||||
"document_id", flat=True
|
||||
traced_documents_ids = (
|
||||
models.LinkTrace.objects.filter(user=user)
|
||||
.exclude(document__link_reach=models.LinkReachChoices.RESTRICTED)
|
||||
.order_by()
|
||||
.values_list("document_id", flat=True)
|
||||
)
|
||||
|
||||
return queryset.filter(
|
||||
db.Q(id__in=access_documents_ids)
|
||||
| (
|
||||
db.Q(id__in=traced_documents_ids)
|
||||
& ~db.Q(link_reach=models.LinkReachChoices.RESTRICTED)
|
||||
)
|
||||
)
|
||||
# A single `IN (... UNION ...)` lets PostgreSQL drive the query from the
|
||||
# (small) set of document ids and probe the primary key index. The
|
||||
# equivalent `id IN (...) OR (id IN (...) AND ...)` results in a sequential
|
||||
# scan of the whole document table.
|
||||
return queryset.filter(id__in=access_documents_ids.union(traced_documents_ids))
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
"""Override to apply annotations to generic views."""
|
||||
|
||||
Reference in New Issue
Block a user