Search code examples
pythonplone

Plone REST API - Filtering search results using a value inside an object


I am trying to use @search or @querystring-search endpoints to limit the response to include only items with priority.token = 1.

An item includes a priority object as follows:

"priority": {
    "title": "1 Important",
    "token": "1"
}

Using @search endpoint, I tried adding priority.token=1, but that resulted in this error:

"Query for index <FieldIndex at priority> is missing a 'query' key!"

So, is it possible to filter the results using a value inside an object? And how to do that?


Solution

  • given, priority is a dict or JSON field, you need an index which only holds the value you are interested in. For that you might need an indexer, which extracts the token value for an index named let's say "priority_token".

    ponecli can help you create a backend addon and an indexer in it, or manually: in zcml register:

    <adapter factory=".priority_token.dummy"
      name="priority_token" />
    
    <adapter factory=".priority_token.priority_token"
      name="priority_token" />
    

    in python priority_token.py:

    from mycustom.contenttypes.content.my_document import IYourDocument
    from plone.dexterity.interfaces import IDexterityContent
    from plone.indexer import indexer
    
    
    @indexer(IDexterityContent)
    def dummy(obj):
        """Dummy to prevent indexing other objects thru acquisition"""
        raise AttributeError("This field should not indexed here!")
    
    
    @indexer(IYourDocument)
    def priority_token(obj):
        """Calculate and return the value for the indexer"""
        return obj.priority.get('token')
    

    for a JSON field you need to convert it into a dict before.

    Now you can register the index it self like this: In ./profiles/default/catalog.xml:

    <?xml version="1.0"?>
    <object name="portal_catalog" xmlns:i18n="http://xml.zope.org/namespaces/i18n">
    
      <index name="priority_token" meta_type="FieldIndex">
        <indexed_attr value="priority_token" />
      </index>
    </object>
    

    After that, you can query it like any other fieldindex.