Catalog Search For Object Review State in Combination With Review State of Parent

I have a dexterity object 'release' which have a parent dexterity object 'project'. I created a portal_catalog search for new releases which have the review state 'final' and display them. I let the user choose the review state of the release. But I don't want to show releases to the public where the review state of their project is not 'published'. Thus I need a switch in my query (or in the function that contains this query) to filter out releases with parents that are not published yet.

My current function is the following:
def get_latest_releases(self):
self.catalog =api.portal.get_tool(name='portal_catalog')
sort_on = 'created'
contentFilter = {'sort_on' : sort_on,
'sort_order' : 'reverse',
'review_state' : 'final',
'portal_type' : (' ' ),
}

    results = self.catalog(**contentFilter)

return results

a simple solution would be to iterate over releases and check if their project is published
(caution: i did not test/verify this pseudo code)

from Acquisition import aq_parent
from plone import api

result = []
releases = api.content.find(portal_type='release', review_state='final', sort...)
for brain in releases:
    release = brain.getObject() # this might be a performance hit if iterating over hundreds or thousands of releases
    if api.content.get_state(aq_parent(release)) == 'published':
        result.append(release)

# result now contains all releases located in a published project

this should be straight forward and not a big performance deal. if you have thousands of releases to iterate over (and can't use pagination and yield) you can alternatively search for published projects first and then limit the search for releases to these projects (works if projects can't be nested)

published_projects = api.content.find(portal_type='project', review_state='published')

# filter by path (multiple paths should work, did not test)
published_paths = [brain.getPath() for brain in published_projects]
release_brains = api.content.find(portal_type='release', path=published_paths, review_state='final')

#filter by uid
release_uids = []
for brain in published_projects:
    project = brain.getObject()
    release_uids += [brain.UID for brain in api.content.find(context=project, portal_type='release')]
releases = api.content.find(UID=release_uids, review_state='final', sort...)

maybe also https://pypi.org/project/Products.AdvancedQuery/ can help you to do more sophisticated queries

Hello Harald,

thanks for your answer. Will try this out next days.

Kind regards,
Andreas

Post-filtering is option as explained.
Another option would be to create a custom index and a custom indexer that would index the state of both objects together in order to query without loading the full objects from the brains.

-aj