I have some indexes in portal_catalog, for various types.
Given a portal_type and a fieldname, how can I find out the name of the index (if any) for that field?
Some relevant pointers to documentation about zcatalog might help me too!
Thanks..
There is no easy one-on-one way to determine this. In Plone 4, there are basically three different ways that an index in the catalog can obtain the information from your content type.
First and foremost, indexes can optionally be configured with the name(s) of the attributes or methods to index on a given object. Indexes generally have a getIndexSourceNames
method that'll tell you what items they'll index.
Usually this is the same as the index id, but this is not a given. Generally, if your field accessor is listed in the result of getIndexSourceNames
then that index will be indexing that field for a given type:
from Products.CMFCore.utils import getToolByName
catalog = getToolByName(context, 'portal_catalog')
for index in catalog.index_objects():
if field.accessor in index.getIndexSourceNames():
print 'Index %s indexes %s' % (index.getId(), field.getName()'
In the above examples, I assumed you already have a hold of your field object in the variable field
, with an actual instance of your type in the variable context
.
When an object is indexed, the catalog also constructs a wrapper around the object and will look up indexing adapters for your object. These adapters are registered both for the indexed name (so the name listed in getIndexSourceNames
) and an interface or class. If your content class implements that interface or has an indexing adapter directly registered for it's class or a base class, the indexing adapter can be brought into play.
Indexing adapters are arbitrary snippets of code, and thus could call any field on your content object to produce their results. There is no programmatic way for you to determine if a given field on your content type will be used, or if any fields will be used at all.
The CMFPlone.CatalogTool
module lists several examples of indexing adapters, these are all registered for Interface
, meaning all objects:
allowedRolesAndUsers
collects security information about your object.
getObjPositionInParent
determines the position of the current object in it's container. Thus, this indexer does not need any information from the object itself to determine it's value.
sortable_title
takes your content Title
value and generates a value suitable for sorting catalog search results with. It normalizes the value, lowercases it, and prefixes numbers with leading zeros to make sorting on numbered titles easier.
Fields are basically generated methods on your content object. But your content class can also implement methods on it's class. The same remarks as for custom indexing adapters apply here; these are arbitrary Python code so they could be using your content type fields, aggregating and mangling the information before passing it to the index.
The Archetypes BaseObject
class (used in all Archetypes content types) defines the SearchableText
method for example. This method takes all available fields with the searchable
property set to True, tries to get each field value as plain text, and aggregates the results for the SearchableText
index.
You can only make educated guesses about index contents as they relate to your fields. By introspecting index configuration, you won't see if there might be a custom indexer adapter masking your field (register a getField
index adapter and it'll be used instead of directly calling getField
). Custom indexers and class methods can still access your fields and pass on the information to a catalog index.
You just add an index for the method or attribute name that you want to use for the index value--there's nothing too tricky about it and it can potentially all be done TTW
If you need a bit more logic to grab the index, check out this stackoverflow question: Problem with plone.indexer and Dexterity