Skip to content

How-to guides

Tuning ranking

Adjust how search results are ordered by relevance without reindexing your data. Use this guide when your index is populated and serving queries, but you want to alter result ordering by applying query boosts, ranking signals, tie breakers, or second-pass rescoring.

Ranking signals, boosts, tie breakers, and rescoring apply only when results are ordered by relevance. An explicit sort parameter overrides relevance ordering.

Before you begin, ensure you have:

  • An index that contains documents.
  • sort or signal enabled on all fields that carry a ranking signal or tie breaker. Enabling either on an existing field is a definition change that requires a reindex. See Rolling out a definition change.
  • An API key with the search and indexes.read permissions.
  • The settings.write permission on your API key to store ranking configurations in search settings.
  1. Inspect current score calculations:

    Find out what the current result order comes from by querying the explain endpoint for a specific hit. See Find out why a result ranked where it did.

    Terminal window
    curl -X POST \
    "$EXOFIND/v1alpha1/indexes/products/search/actions/explain?key=item-101" \
    -H "Authorization: Bearer $KEY" \
    -H "Content-Type: application/json" \
    -d '{
    "query": [
    { "type": "text", "text": "running shoes", "fields": { "name": null } }
    ]
    }'

    Inspect the detail tree in the response to review match scores and ranking signal contributions for each clause.

  2. Lift documents with a boost clause:

    Add a boost clause to your search request to promote matching documents without filtering out non-matching documents:

    {
    "query": [
    { "type": "text", "text": "running shoes", "fields": { "name": null } },
    {
    "type": "boost",
    "weight": 1.5,
    "clauses": [
    { "field": "featured", "match": { "value": true } }
    ]
    }
    ]
    }

    Set weight greater than 1 to increase the score of matching items, or between 0 and 1 to decrease their score.

  3. Rank by document values with ranking signals:

    Use ranking signals to adjust relevance scores based on document values. Configure saturation on number fields (such as sales or purchases), linear on a number field holding a score that already lies in a known range (such as an engagement score between 0 and 1), or decay on timestamp fields (such as publication dates). You can set an optional weight multiplier (default 1). To refresh a score across the catalogue without indexing the documents again, declare its field as a signal field with signal enabled. This is a storage mode and not a ranking rule. Send the new values through the update action. See Signal fields and Refresh a ranking signal across the catalogue.

    Choose one of the following two options depending on your goal:

    1. Store ranking signals in search settings: Store ranking signals in search settings so every caller receives them by default. Fetch the current settings version, then send a PUT request with an If-Match header:

      Terminal window
      curl -X PUT \
      "$EXOFIND/v1alpha1/admin/indexes/products/settings" \
      -H "Authorization: Bearer $KEY" \
      -H "Content-Type: application/json" \
      -H 'If-Match: "9f2c1a0b3d4e5f60"' \
      -d '{
      "ranking": {
      "signals": [
      { "field": "purchases", "saturation": { "pivot": 50 }, "weight": 1.0 },
      { "field": "published", "decay": { "halfLife": 604800 }, "weight": 0.5 }
      ]
      }
      }'

      While the search settings carry a ranking, it replaces the definition’s ranking completely, tie breakers included, so any tie breaker the definition declares must be carried over into the settings. Search settings take effect immediately on the holding node and within EXOFIND_SETTINGS_REFRESH_INTERVAL (default 10 seconds) on other nodes.

    2. Send ranking signals in the search request: Pass signals directly in a search query using signalsMode. Set "signalsMode": "replace" to try a complete ranking before storing it, or "signalsMode": "add" (default) to layer per-request ranking signals (such as user affinity) on top of the index’s stored ranking:

      {
      "query": [
      { "type": "text", "text": "running shoes" }
      ],
      "signals": [
      { "field": "brandAffinity", "saturation": { "pivot": 5 }, "weight": 1.2 }
      ],
      "signalsMode": "add"
      }
  4. Break score ties with tie breakers:

    Define tieBreakers in the ranking configuration to resolve ordering when documents share identical relevance scores. Set the target field and sort direction ("ascending" or "descending"):

    {
    "ranking": {
    "tieBreakers": [
    { "field": "popularity", "direction": "descending" },
    { "field": "id", "direction": "ascending" }
    ]
    }
    }

    Exofind evaluates tie breakers in sequence until the tie between two documents is resolved.

  5. Rescore top results in a second pass:

    Add a rescore block to the search request to apply expensive scoring rules or user personalization only to the best first-pass results:

    {
    "query": [
    { "type": "text", "text": "running shoes" }
    ],
    "rescore": {
    "window": 200,
    "boost": [
    { "field": "brand", "match": { "value": "aurora" } }
    ],
    "signals": [
    { "field": "purchases", "saturation": { "pivot": 50 } }
    ],
    "weight": 0.5
    }
    }

    The second pass scores only the window results, so it is where per-request work too expensive for every match belongs. Paging inside the window counts results using offsets, while cursors past the window continue in the order relevance originally ranked them without second-pass scoring.

  6. Check the outcome with explain:

    Call the explain endpoint again to verify how your ranking adjustments affect document scores.

    Note: The explain endpoint ignores rescore and explains only the first-pass relevance score.

Execute a search query without explicit sorts to verify that documents return in the expected order:

Terminal window
curl -X POST \
"$EXOFIND/v1alpha1/indexes/products/search" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"query": [
{ "type": "text", "text": "running shoes" }
]
}'

Inspect the returned hits array to verify that boosted items and documents with high ranking signal values rank higher in the relevance order.

Exofind is built by Level Four AB and is available under the Apache License 2.0.