diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index a9bdd1b0..392c760f 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -1005,7 +1005,4 @@ class SearchDocumentSerializer(serializers.Serializer): """Serializer for fulltext search requests through Find application""" q = serializers.CharField(required=True, allow_blank=False, trim_whitespace=True) - page_size = serializers.IntegerField( - required=False, min_value=1, max_value=50, default=20 - ) - page = serializers.IntegerField(required=False, min_value=1, default=1) + path = serializers.CharField(required=False, allow_blank=False) diff --git a/src/backend/core/api/viewsets.py b/src/backend/core/api/viewsets.py index 5d9bd360..916fce31 100644 --- a/src/backend/core/api/viewsets.py +++ b/src/backend/core/api/viewsets.py @@ -1402,7 +1402,7 @@ class DocumentViewSet( Returns a queryset filtered by the content of the document title """ # As the 'list' view we get a prefiltered queryset (deleted docs are excluded) - queryset = self.get_queryset() + queryset = models.Document.objects.all() filterset = DocumentFilter({"title": text}, queryset=queryset) if not filterset.is_valid(): @@ -1417,58 +1417,48 @@ class DocumentViewSet( }, ) - def _search_fulltext(self, indexer, request, params): + @staticmethod + def _search_with_indexer(indexer, request, params): """ - Returns a queryset from the results the fulltext search of Find + Returns a list of documents matching the query (q) according to the configured indexer. """ - access_token = request.session.get("oidc_access_token") - user = request.user - text = params.validated_data["q"] queryset = models.Document.objects.all() - # Retrieve the documents ids from Find. results = indexer.search( - text=text, - token=access_token, - visited=get_visited_document_ids_of(queryset, user), + q=params.validated_data["q"], + token=request.session.get("oidc_access_token"), + path=( + params.validated_data["path"] + if "path" in params.validated_data + else None + ), + visited=get_visited_document_ids_of(queryset, request.user), ) - docs_by_uuid = {str(d.pk): d for d in queryset.filter(pk__in=results)} - ordered_docs = [docs_by_uuid[id] for id in results] - - page = self.paginate_queryset(ordered_docs) - - serializer = self.get_serializer( - page if page else ordered_docs, - many=True, - context={ - "request": request, - }, + return drf_response.Response( + { + "count": len(results), + "next": None, + "previous": None, + "results": results, + } ) - return self.get_paginated_response(serializer.data) - @drf.decorators.action(detail=False, methods=["get"], url_path="search") @method_decorator(refresh_oidc_access_token) def search(self, request, *args, **kwargs): """ - Returns a DRF response containing the filtered, annotated and ordered document list. + Returns an ordered list of documents best matching the search query parameter 'q'. - Applies filtering based on request parameter 'q' from `SearchDocumentSerializer`. - Depending of the configuration it can be: - - A fulltext search through the opensearch indexation app "find" if the backend is - enabled (see SEARCH_INDEXER_CLASS) - - A filtering by the model field 'title'. - - The ordering is always by the most recent first. + It depends on a search configurable Search Indexer. If no Search Indexer is configured or if it + is not reachable, the function falls back to a basic title search. """ params = serializers.SearchDocumentSerializer(data=request.query_params) params.is_valid(raise_exception=True) indexer = get_document_indexer() - if indexer: - return self._search_fulltext(indexer, request, params=params) + return self._search_with_indexer(indexer, request, params=params) # The indexer is not configured, we fallback on a simple icontains filter by the # model field 'title'. diff --git a/src/backend/core/services/search_indexers.py b/src/backend/core/services/search_indexers.py index a4bb9eec..28efd890 100644 --- a/src/backend/core/services/search_indexers.py +++ b/src/backend/core/services/search_indexers.py @@ -185,7 +185,7 @@ class BaseDocumentIndexer(ABC): """ # pylint: disable-next=too-many-arguments,too-many-positional-arguments - def search(self, text, token, visited=(), nb_results=None): + def search(self, q, token, visited=(), nb_results=None, path=None): """ Search for documents in Find app. Ensure the same default ordering as "Docs" list : -updated_at @@ -193,7 +193,7 @@ class BaseDocumentIndexer(ABC): Returns ids of the documents Args: - text (str): Text search content. + q (str): Text search content. token (str): OIDC Authentication token. visited (list, optional): List of ids of active public documents with LinkTrace @@ -201,21 +201,24 @@ class BaseDocumentIndexer(ABC): nb_results (int, optional): The number of results to return. Defaults to 50 if not specified. + path (str, optional): + The path to filter documents. """ nb_results = nb_results or self.search_limit - response = self.search_query( + results = self.search_query( data={ - "q": text, + "q": q, "visited": visited, "services": ["docs"], "nb_results": nb_results, "order_by": "updated_at", "order_direction": "desc", + "path": path, }, token=token, ) - return [d["_id"] for d in response] + return results @abstractmethod def search_query(self, data, token) -> dict: