Faceted Search with Volto Search Block - adding new facets

It seems that the Volto Search Block comes with facets such as 'review state' and 'type'. How do I go about adding additional facets? E.g. filtering by tag.

It's due to this function here: volto/schema.js at 4a760bde9bc2ea8050d7a16f2b518e244d415536 Β· plone/volto Β· GitHub There's some comments there mentioning the need for improvements.

I've tested, and if you remove that function the Subject (Tags) index actually shows up as an available facet (and works in the search block view mode). You could try to write a schemaEnhancer function for the search block that removes that property (or shadow customize the schema.js module), to remove the function.

It seems that tags were not offered as facets out of the box. But it looks like it is out of the box now with Volto 16 and above.

I'm still looking for the most straightforward and elegant way to add new criteria/facets:
I thought that creating an index and FieldIndex-based metadata was enough to make my metadata show up in the base query for Faceted Search on the Search Block

What step am I missing to do this?

Visit our training!

@ksuess,
Thank you very much. This is really helpful.
In my case, I have an index and metadata called document_type

Based on the training docs that you shared, It looks like I will need to do something like the code below in my default/profile/registry/querystring.xml:

For clarification:

  1. Is the prefix just for namespacing?
    If so, I figure I can just do prefix="plone.app.querystring.field.document_type"
  2. I'm guessing I'll need to create my own vocabulary that returns the available document_types here:
    <value key="vocabulary">??????????</value>
<?xml version="1.0"?>
<registry xmlns:i18n="http://xml.zope.org/namespaces/i18n"
          i18n:domain="plone">

<records interface="plone.app.querystring.interfaces.IQueryField"
           prefix="plone.app.querystring.field.document_type"
  >
    <value key="title"
           i18n:translate=""
    >Type</value>
    <value key="description"
           i18n:translate=""
    >Type of document</value>
    <value key="enabled">True</value>
    <value key="sortable">False</value>
    <value key="operations">
      <element>plone.app.querystring.operation.selection.any</element>
      <element>plone.app.querystring.operation.selection.none</element>
    </value>
    <value key="vocabulary">??????????</value>
    <value key="group"
           i18n:translate=""
    >Metadata</value>
  </records>

</registry>

Update, here is where I've reached (for my future self as usual).

I registered a vocabulary named my.content.document_types (see below how I did it) :point_down:

Now I can use this named vocabulary in my querystring.xml

<records interface="plone.app.querystring.interfaces.IQueryField"
           prefix="plone.app.querystring.field.document_type"
  >
    <value key="title"
           i18n:translate=""
    >Type</value>
    <value key="description"
           i18n:translate=""
    >Type of document</value>
    <value key="enabled">True</value>
    <value key="sortable">False</value>
    <value key="operations">
      <element>plone.app.querystring.operation.selection.any</element>
      <element>plone.app.querystring.operation.selection.none</element>
    </value>
    <value key="vocabulary">my.content.document_types</value>
    <value key="group"
           i18n:translate=""
    >Metadata</value>
  </records>

</registry>

Registering the vocabulary

# this is vocabularies/document_types.py
from zope.interface import provider
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
from Products.CMFCore.utils import getToolByName
from zope.schema.interfaces import IVocabularyFactory

@provider(IVocabularyFactory)
def document_type_vocabulary_factory(context):
    catalog = getToolByName(context, 'portal_catalog')

    # Get all unique values of the 'document_type' index
    document_types = catalog.uniqueValuesFor('document_type')

    # Create a list of SimpleTerm objects
    terms = [SimpleTerm(value=t, token=t, title=t) for t in document_types]

    # Return a SimpleVocabulary
    return SimpleVocabulary(terms)

here's the configure.zcml

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

    <!-- -*- extra stuff goes here -*- -->
 <utility
        component=".document_types.document_type_vocabulary_factory"
        name="my.content.document_types"
    />



</configure>

I have a vocabularies folder for the vocabulary with it's own configure.zcml

β”œβ”€β”€ browser
β”‚ 
└── vocabularies
    └── configure.zcml
    └── document_types.py

This is quite involved:
Had to add an upgrade step, since my addon is already deployed:

 <genericsetup:upgradeStep
      title="Update querystring configuration"
      description="Apply new querystring.xml settings"
      source="1014"
      destination="1015"
      handler=".upgrades.add_querystring.upgrade_to_1015"
      sortkey="1"
      profile="my.content:default" />

Here's what the upgrade code looks like:

from plone import api
from plone.registry.interfaces import IRegistry
from zope.component import getUtility

def update_querystring_config(context):
    # Get the registry
    registry = getUtility(IRegistry)

    # Import the registry settings
    context.runImportStepFromProfile('profile-my.content:default', 'plone.app.registry')

    # Optionally, you can perform additional operations here

    return "Updated querystring configuration"

def upgrade_to_1015(context):
    # Run the function to update querystring config
    update_querystring_config(context)

    # Optionally, run other upgrade tasks here

    return "Added querystring.xml with document_types so that it shows in faceted search box"

You don't have to write any Python code to simply run a GenericSetup import step as an upgrade step. You can use an upgradeDepends directive instead:

  <genericsetup:upgradeDepends
      title="Update querystring configuration"
      profile="my.content:default"
      source="1014"
      destination="1015"
      import_steps="plone.app.registry"
      />
1 Like

Ah!!! much better!

Okay... I've run the updates and should now have my new vocabulary and querystrings installed.

When I go to my listing block, I still don't see a "document_types" option under the criteria.

I'm clearly missing something, absolutely no sign of "document_types"
Edit Page

@pigeonflight In your code for querystring.xml above you gave it the title Type, which does appear in the list in your video.

You're right! Thanks for noticing that @davisagli
Type does in fact now use my defined vocabulary...
But it is now overriding the default Type (Event, Document etc..) :sob: ...
off to fix it now!

Got it working now, my querystring.xml now looks like this:

<?xml version="1.0"?>
<registry xmlns:i18n="http://xml.zope.org/namespaces/i18n"
          i18n:domain="plone">

<records interface="plone.app.querystring.interfaces.IQueryField"
           prefix="plone.app.querystring.field.document_type"
  >
    <value key="title"
           i18n:translate=""
    >Document Type</value>
    <value key="description"
           i18n:translate=""
    >An item's document type (e.g. Article, Note)</value>
    <value key="enabled">True</value>
    <value key="sortable">False</value>
    <value key="operations">
      <element>plone.app.querystring.operation.selection.any</element>
      <element>plone.app.querystring.operation.selection.none</element>
    </value>
    <value key="vocabulary">my.content.document_types</value>
    <value key="group"
           i18n:translate=""
    >Metadata</value>
  </records>

</registry

Got it working!
Thank you @tiberiuichim, @ksuess and @davisagli

1 Like