Troubleshooting: Series Unified Manifest: Canvas Sort Order

Summary

Canvases in manifests generated by the IIIF Presentation API 3 Series Manifest Unified metadata display were ordered lexically (1, 10, 11, 2, 3, ...) instead of by each child object’s sequence_id. The template was not at fault. The ordering comes from the Drupal View that supplies the child objects, and that View sorted only on a field that does not sort numerically. Adding a sequence_id_1 sort criterion ahead of the existing one restored the expected order.

Background

Neither Series template sorts canvases itself. Each one loops over the rows a Drupal View returns and emits canvases in that order, so canvas order is entirely determined by the View’s sort criteria.

The two templates use different Views:

Series Manifest (older)

Series Manifest Unified (newer)

Template

IIIF_Presentation_API_3_Creative_Works_Series_Manifest.twig.html (with ..._Series_Child_Canvases.twig.html rendering each child)

IIIF_Presenation_API_3_Series_Manifest_Unified.twig.html

View / display

data_creativeworks_series / children_ispartof_canvas_rest

data_creativeworks_series_multiple_levels / children_raw_json

Children fetched

Direct children only (nid_ref_partof)

Up to three levels (nid_ref_partof, nid_ref_partof_partof, nid_ref_partof_partof_partof)

Paging

Single request, up to 2000 items

Paged, 10 items per page

Sort criteria (before fix)

sequence_id_1 ASC

aggregated_sequence_id ASC

The Unified template calls its View like this:

{%- set raw_json_view = sbf_drupal_view_paged(
      'data_creativeworks_series_multiple_levels', 'children_raw_json', page,
      {'nid_ref_partof': nodeid,
       'nid_ref_partof_partof': nodeid,
       'nid_ref_partof_partof_partof': nodeid}, 'all')|render -%}

Root cause

data_creativeworks_series_multiple_levels sorted only on aggregated_sequence_id. That field is a Search API aggregated field: it combines sequence IDs from several levels of the hierarchy into one value so that grandchildren can be ordered under their parents. Because the value is built from several parts, Solr sorts it as text, character by character. As a result:

  • "10" sorts before "2".

  • In multi-level values, "1 10 ..." sorts before "1 2 ...".

The older View sorted on sequence_id_1, a separate per-object index field that orders direct children numerically, which is why the older Series Manifest never showed the problem.

Note

sequence_id values arrive from AMI CSVs as strings (the AMI ingest template passes them through with json_encode), so how the value sorts depends entirely on the Type assigned to the field in the Search API index, not on the JSON.

Fix

Add sequence_id_1 as the first sort criterion on the Unified View and keep aggregated_sequence_id after it.

  1. Go to Structure → Views → Data CreativeWorks Series multiple Levels (/admin/structure/views/view/data_creativeworks_series_multiple_levels/edit/children_raw_json).

  2. Under Sort criteria, click Add, choose the field whose machine name is sequence_id_1, and set the order to Asc.

  3. Open the dropdown next to Add in Sort criteria, choose Rearrange, and drag sequence_id_1 above aggregated_sequence_id.

  4. Click Apply, then Save the View.

  5. Clear caches so cached manifests are regenerated:

    drush cr
    

Resulting sort criteria:

sorts:
  sequence_id_1:          # numeric order of each child
    order: ASC
  aggregated_sequence_id: # tie-breaker across hierarchy levels
    order: ASC

Note

children_raw_json does not override its sorts, so it inherits them from the View’s Default display. Leaving For: All displays selected changes the Default display, which is fine because this View has no other displays.

Known limitation

Sorting on sequence_id_1 first compares each object’s own sequence ID. For a Series with multiple levels (for example a grandchild whose parent is also a child of the Series), a grandchild’s own sequence ID is compared directly against its parent’s siblings. If deeply nested Series come out out of order, the full fix is to make aggregated_sequence_id sort correctly as a string, for example by zero-padding sequence IDs (0001, 0012) and re-indexing.

Investigating similar issues

Finding the View a template uses

Search the template for drupal_view( or sbf_drupal_view_paged(. The first two arguments are the View machine name and the display ID.

Finding a sort field’s machine name and type

Views shows only field labels. Go to Configuration → Search and metadata → Search API → Default Solr Index → Fields (/admin/config/search/search-api/index/default_solr_index/fields). The table lists each field’s label, machine name, property path, and type. For an aggregated field, click Edit to see its aggregation type and source fields.

Exporting View or index config from the cluster

Run from your workstation; output is written locally:

kubectl exec $(kubectl get pods -o name | grep esmero-php) -- \
  sh -c 'cd /var/www/html && drush config:get views.view.data_creativeworks_series' \
  > data_creativeworks_series.yml

Do not pass -it. A TTY adds carriage returns to the output.