Re-indexing Collections

If you’ve worked with Perch Runway’s Collections, you probably know that it’s a good idea not to index all fields. To set a field not to be indexed you add the no-index attribute:

<perch:content id="some_field" type="text" label="Some Field" no-index>

You normally only want to index fields that you need to filter and/or sort by. The more fields you index, the more likely your queries going to be slower (though this depends on other factors too).

Why re-index?

Requirements and/or features may change over a site’s lifespan. You may need to index fields that were set not to be indexed in the past. Or perhaps you’re adding a new field that must be indexed for all Collection items for you to start filtering by it.

Your first step would be to modify your template whether you’re adding new fields or removing some no-indexs. Then, you’d want to re-index the items of that Collection.

If you only have a small number of items, you can go to each item in the control panel and re-save them one by one. When you save an item, the fields will be re-indexed.

What would you do if you have hundreds of items? Re-saving each item via the control panel is going to take ages.

Luckily, the Perch API allows you to programmatically update Collection items. Meaning you can update all items in a given Collection via the API instead of the control panel. And when you update an item, its fields are re-indexed.

Import API

The API is very well documented. You can find the documentation here. So I’m going to assume you know the basics:

$API      = new PerchAPI(1.0, 'my_importer');
$Importer = $API->get('CollectionImporter');
$Importer->set_collection('Articles');

$Template = $API->get('Template');
$Template->set('content/my_article', 'content');

$Importer->set_template($Template);

Finding items

To find the items you want to update you use find_items(), which takes an optons array so you can filter the items just like you do with perch_collection():

$items = $Importer->find_items([
    'filter' => 'slug',
    'value' => 'hello-world',
]);

In our case we want all items in the Collection, so we can pass an empty array without any filters:

$items = $Importer->find_items([]);

Then you can loop over the returned items like so:

if (count($items)) {
   foreach($items as $item) {
      // update item
   }
}

Updating an item

To update an item you use update_item(). The function takes 2 arguments:

  1. The item ID $item['_id']; this value is automatically assigned to the item by Perch
  2. An array of the fields you want to change
if (count($items)) {
   foreach($items as $item) {
      $Importer->update_item($item['_id'], [
         'title' => 'My New Title',
         'slug' => ''
      ]);    
   }
}

Re-indexing: Existing Field

If you simply just want to re-index the existing fields, you can update a random existing field with its existing value (so you’re not actually changing any content):

if (count($items)) {
   foreach($items as $item) {
      $Importer->update_item($item['_id'], [
         'title' => $item['title'],
      ]);    
   }
}

Indexig new fields

If you add a new field that you want to index, you have to add it; at least with a false value.

Thanks to Ryan Gittings for pointing this out.

if (count($items)) {
   foreach($items as $item) {
      $Importer->update_item($item['_id'], [
         'my_new_field' => false,
      ]);    
   }
}
link