Add an index to the user catalog#
The user catalog is declared in profiles/default/identity-catalog.xml and
applied by the identity-catalog GenericSetup step. Adding an index is an edit
to that file.
Why you would#
A metadata column is what the PAS property sheet and enumeration read. Both are served from brains alone, so a field with no column cannot be answered without waking the Profile object—which is what a property sheet must never do.
An index is what lets a query match on the field. Add one when something looks a principal up by it, rather than reading it off a principal it already has.
A field a site added through its own behavior gets neither by default.
Add it#
Add the entry to
identity-catalog.xml:<index name="nickname" meta_type="FieldIndex"> <indexed_attr value="nickname"/> </index> <column value="nickname"/>
If the value is not a plain attribute read—folded, narrowed, or derived—add an indexer to
core/indexers/profile.pyand register it in that package'sconfigure.zcml:@indexer(IUserProfile) def nickname_index(obj: UserProfile) -> str: return (obj.nickname or "").casefold()
<adapter factory=".profile.nickname_index" name="nickname" />
loginis the worked example: it is case-folded at index time, so every caller case-folds at query time too.If it is a column, add it to
PROFILE_METADATAorGROUP_METADATAincore/catalog.py. One schema serves both types, so a column that means nothing on the other one is blank there, and those two tuples are what tell the consistency check to expect the blank rather than report it as drift.Apply the profile, then rebuild:
# in the add-ons control panel, or from a script portal_setup.runImportStepFromProfile( "pas.plugins.identity:default", "identity-catalog" )
Important
Applying the profile does not populate the index.
The step creates the index empty, and addColumn fills existing records with a
default rather than with the value. Every brain reads as blank for the new field
until something reindexes—and a query against an empty index answers "nothing
matched" rather than failing, so the mistake is silent.
Apply pas.plugins.identity:rebuild-catalog afterwards. See
Upgrade.
Remove one#
<index name="nickname" meta_type="FieldIndex" remove="True"/>
<column value="nickname" remove="True"/>
Removing an index that is not there is not an error, so a profile carrying this stays re-runnable.
Why the file is not called catalog.xml#
GenericSetup's own catalog step resolves its target with
queryUtility(ICatalogTool), which answers portal_catalog and nothing else.
It has no notion of a second catalog.
A catalog.xml in this package's profile is therefore not ignored. It is
read by that step and applied to the site catalog, adding this package's indexes
to portal_catalog, silently. The separate filename is what keeps the two
apart, and IdentityCatalogXMLAdapter exists to change it—everything else about
reading a ZCatalog from XML is inherited from GenericSetup.