zc.relation provides powerful indexing features, half of which are still over my head.
Consider the following use case. Suppose I have a set of questions, which are represented by a Question content type, and a number of answers, represented by an Answer content type. Further suppose that each answer object has a reference, by means of z3c.relationfield, to the Question it answers, and that each of the users on your plone site gets to answer the question once.
Suppose your context is a question, and you want to quickly find Joe's answer to the question in context, how would you do it?
From what my research told me, this isn't possible without iterating through answers for the question, looking for Joe's, or through some other means of indexing. The solution I came up with, eventually, was to add another index to the relation catalog, so that I could limit the results to a specific user. This is how I did it.
import BTrees from zope.component import getUtility from zc.relation.interfaces import ICatalog def from_creator(i, catalog): """ This is an indexer for the Creator of the from-end of a relation, allowing us to do a lookup for objects belonging to a specific user. """ return i.from_object.Creator() catalog.addValueIndex(from_creator, btree=BTrees.family32.OI)
With this extra index in place, it is now possible to find Joe's answer.
from zope.component import getUtility from zope.app.intid.interfaces import IIntIds from zc.relation.interfaces import ICatalog intids = getUtility(IIntIds) catalog = getUtility(ICatalog) relations = catalog.findRelations({ 'to_id': intids.getId(question), 'from_creator': 'Joe' }) answers = [relation.from_object for relation in relations]
Since the catalog is persistent, you need to add this index only once, likely in your setuphandlers.
idxs = [x['name'] for x in catalog.iterValueIndexInfo()] if not 'from_creator' in idxs: catalog.addValueIndex(from_creator, btree=BTrees.family32.OI)