Indexing#

To make Plone content searchable, one can use different indexes to index content.

The most important index types are the following.

  • FieldIndex

  • KeywordIndex

  • DateIndex

  • DateRangeIndex

  • BooleanIndex

  • ZCTextIndex

The most important indexes are described in the following sections.

SearchableText#

The SearchableText is a ZCTextIndex for indexing full text. It is used by default for Dublin Core fields such as Title, Description, and Text.

TextIndexer#

To add other fields to the SearchableText, one can use the plone.app.dexterity.textindexer.

For enabling the indexer, add the behavior to the list of behaviors of your content types.

In your profiles/default/types/YOURTYPE.xml add the behavior.

<?xml version="1.0"?>
<object name="example.conference.presenter" meta_type="Dexterity FTI"
   xmlns:i18n="http://xml.zope.org/namespaces/i18n"
   i18n:domain="example.conference">

 <!-- enabled behaviors -->
 <property name="behaviors" purge="false">
     <element value="plone.textindexer" />
 </property>
</object>

Now you need to mark the fields you want to have in your SearchableText. This can be done with the searchable directive.

from plone.app.dexterity import textindexer
from plone.supermodel.model import Schema
from plone import schema

class IMyBehavior(Schema):

    textindexer.searchable('specialfield')
    specialfield = schema.Text(title=u'Special field')

If you want to mark fields of an existing third party behavior, it can be done using the following utility function.

from plone.app.dexterity.behaviors.metadata import ICategorization
from plone.app.dexterity.textindexer import utils

utils.searchable(ICategorization, 'categorization')

The title and description on plone.app.dexterity's IBasic behavior are marked as searchable by default. For marking them as no longer searchable, there is a utility function.

from plone.app.dexterity.behaviors.metadata import IBasic
from plone.app.dexterity.textindexer import utils

utils.no_longer_searchable(IBasic, 'title')

Alternatively, if you specified your model as a plone.supermodel XML model, you can mark the field searchable by using indexer:searchable="true".

<model xmlns="http://namespaces.plone.org/supermodel/schema"
        xmlns:indexer="http://namespaces.plone.org/supermodel/indexer">
    <schema based-on="plone.supermodel.model.Schema">

        <field name="specialfield" type="zope.schema.TextLine"
                indexer:searchable="true">
        <title>Special field</title>
        </field>

    </schema>
</model>

The SearchableText indexer now includes your custom field on your behavior. The field of your content type is indexed if the plone.textindexer behavior is enabled on your content type.

Registering a custom field converter#

By default a field is converted to a searchable text by rendering the widget in display mode and transforming the result to text/plain. However if you need to convert your custom field in a different way, you have to provide a more specific converter multi-adapter.

Convert multi-adapter specification#

Interface

plone.app.dexterity.textindexer.IDexterityTextIndexFieldConverter

Discriminators

context, field, widget

Example:

from plone.app.dexterity.textindexer.converters import DefaultDexterityTextIndexFieldConverter
from plone.app.dexterity.textindexer.interfaces import IDexterityTextIndexFieldConverter
from my.package.interfaces import IMyFancyField
from plone.dexterity.interfaces import IDexterityContent
from z3c.form.interfaces import IWidget
from zope.component import adapter
from zope.interface import implementer

@implementer(IDexterityTextIndexFieldConverter)
@adapter(IDexterityContent, IMyFancyField, IWidget)
class CustomFieldConverter(DefaultDexterityTextIndexFieldConverter):

    def convert(self):
            # implement your custom converter
            # which returns a string at the end
            return ''

ZCML:

<configure xmlns="http://namespaces.zope.org/zope">

    <adapter factory=".converters.CustomFieldConverter" />

</configure>

There is already an adapter for converting files properly.

Extending indexed data#

Sometimes you need to extend the SearchableText with additional data which is not stored in a field. It is possible to register a named adapter which provides additional data.

from plone.app.dexterity import textindexer
from zope.component import adapter
from zope.interface import implementer


@implementer(textindexer.IDynamicTextIndexExtender)
@adapter(IMyBehavior)
class MySearchableTextExtender(object):

    def __init__(self, context):
        self.context = context

    def __call__(self):
        """Extend the searchable text with a custom string"""
        return 'some more searchable words'

ZCML:

<configure xmlns="http://namespaces.zope.org/zope">

    <adapter factory=".indexer.MySearchableTextExtender"
                name="IMyBehavior"
                />

</configure>

This is a named adapter! The named registration allows registering multiple extenders on different behavior interfaces applying to the same object. The name of the adapter does not matter, but it's recommended to use the name of the behavior to reduce potential conflicts.

If your behavior has a defined factory (which is not attribute storage), then you need to define a marker interface and register the adapter on this marker interface. Dexterity objects do not provide behavior interfaces of behaviors, which are not using attribute storage.

portal_type (FieldIndex)#

Indexes the portal_type field and contains values such as Folder.

path (PathIndex)#

Indexes the object path, such as /news/news-item-1.

Subject (KeywordIndex)#

Indexes the Subject field which contains a list of object categories.