Rest API - Ordering for Search-Endpoint not working

I found, that the _ordering parameter for the /search/{search_model_pk}/ does not work. Please consider the following python sample:

import requests

r = requests.get(url='https://.../api/v4/search/documents.documentsearchresult/?q=.*&_ordering=-label', auth=(...)).json()

for r in r['results']:
    print(r['label'])

# output
# 1.pdf
# 2.pdf
# 3.pdf

This code is printing document labels but does not order them as wanted.
When doing the same for the documents endpoint, everything is working as expected:

r = requests.get(url='https://.../api/v4/documents/?_ordering=-label', auth=(...)).json()

# output
# 3.pdf
# 2.pdf
# 1.pdf

What is wrong with my sample?

Thanks, Torsten

The search API endpoint is very different from other endpoints because it is an endpoint that can return any time of object. Django REST framework requires the ordering fields to be specified at design time and cannot be dynamic.

class APITagListView(generics.ListCreateAPIView):
    """
    get: Returns a list of all the tags.
    post: Create a new tag.
    """
    mayan_object_permissions = {
        'GET': (permission_tag_view,)
    }
    mayan_view_permissions = {
        'POST': (permission_tag_create,)
    }
    ordering_fields = ('id', 'label')  # Static ordering fields are defined here.
    serializer_class = TagSerializer
    source_queryset = Tag.objects.all()

    def get_instance_extra_data(self):
        return {
            '_event_actor': self.request.user
        }

This is a limitation of the REST API library and not of Mayan. This duplication of model ordering knowledge causes other problems and we’ve been discussing methods to extract the ordering knowledge from the model itself instead of being forced to hard code the fields in the view. An added automatic benefit of this improvements would be allowing ordering of the search API results.

Ok I understand. Thanks for your reply.

Is there an alternative way of searching without using the search endpoint? For example using the document list endpoint? Is it possible to append a search query for OCR words or metadata fields there? url=‘http…/documents/?q=invoice AND mystore’

It would be nice to have a document endpoint for both searching and ordering.

Thx

Yes, this was added in version 4.4

The AND operator is the default so there is no need to specify it.

/api/v4/documents/?filter_versions__version_pages__ocr_content__content=term1%20term2

/api/v4/documents/?filter_versions__version_pages__ocr_content__content=term1+term2

Only fields configures for search are available for filtering. These can be obtained with the API /api/v4/search_models/

Thanks Roberto,

now it is getting clear. To complete this topic here is a working example with ordering, paging and filtering from my initial question:

import requests

r = requests.get(url='https://.../api/v4/search/documents.documentsearchresult/?_ordering=-label&page=1&page_size=100&filter_q=test', auth=(...)).json()

for r in r['results']:
    print(r['label'])

May these information be added to the Swagger documentation in the future? In my opinion it would be helpful to find more hints there about all available parameters for each endpoint (plus examples as a bonus :upside_down_face:)

Best regards

Swagger does not provide an easy way to document these options or add client examples for multiple languages (not everybody uses Python to connect to Mayan’s API and just API examples for popular JavaScript libraries would fill a book).

We only add documentation if it can be managed in an automated manner. Adding documentation by hand is an entire project on its own and opens up a can of worms on each release if things change.

Perhaps this could change when Mayan reaches a customer count where an employee can be hired to work solely on documentation.

Based on the comments above there is another question for the “simple” api filter:

I have two filters working fine on their own:

/api/v4/documents/?filter_metadata__value=12345
/api/v4/documents/?filter_metadata__metadata_type__name=FieldA

What does the url need to look like when combining them (seach meta field name AND its value)?

I already tried the following combinations, but they are not working:

/api/v4/documents/?filter_metadata__value=12345&metadata__metadata_type__name=FieldA

/api/v4/documents/?filter_metadata__value=12345+metadata__metadata_type__name=FieldA

/api/v4/documents/?filter_metadata__value=12345&filter_metadata__metadata_type__name=FieldA

I dont know the correct way for joining both expressions for the simple filter. I found some examples for using the advanced search, but none for the use of the “filter” argument.

Best regards,
Torsten

Almost there, just need to add the filter_ prefix to each key:

/api/v4/documents/?filter_metadata__value=12345&filter_metadata__metadata_type__name=FieldA

Thanks a lot.
It seems that both filters are OR-related. Is there also a possibility to make them …AND… connected?

SEARCH_DEFAULT_OPERATOR is already set to AND.


EDIT 1:
I guess I found what I was looking for: just have to add &filter__match_all=true right?


EDIT 2:
Sorry, better but… still not right :roll_eyes: The result of EDIT 1 is that the record is found if it has any Metadata Field named FieldA and any (other) Metadata Field with a value 12345. But the problem is that I would like to find the document with the (one) specific Metadata Field with the name FieldA and also the value 12345. How could this be achieved with the filter argument?