Skip to content

op=index: rank results by Levenshtein distance + actuality score #153

Description

@bmarwell

Background

The HKP op=index endpoint currently returns results in an unspecified order (database insertion order). For a good user experience — especially for email or UID substring searches that may match many keys — results should be ranked by relevance.

Proposed ranking model

A combined score of two dimensions:

  1. Edit-distance relevance — Levenshtein distance between the search term and the best-matching UID string. A lower distance means a better match. Can be normalised to [0, 1] as distance / max(len(term), len(uid)).
  2. Actuality — recency of the key, measured by mtime (last modification time). A more recently updated key is weighted as more relevant.

A blended score e.g. 0.7 × normalised_levenshtein + 0.3 × normalised_age could be tuned later.

Implementation considerations

  • Levenshtein distance is not available as a standard JPQL function. Options:
    • PostgreSQL levenshtein() via a native query or a JPA function extension.
    • Pre-compute a normalised string representation in the DB for faster matching.
    • Compute in Java after loading the bounded result set (at most 5 000 entries).
  • The two-query pattern introduced in the N+1 fix (issue feat: implement HKP op=index in LookupEndpoint #137 / PR feat: implement HKP op=index (#137) #152) can be extended: the fingerprint-selection query can ORDER BY a DB-computed score, passing that ordering through to the second fetch.
  • A Java-side sort after the second fetch is simpler and provider-agnostic; with the 5 000-row cap the overhead is acceptable.

Acceptance criteria

  • Email/UID substring searches return results ordered by the combined score (best match first).
  • Fingerprint/key-ID searches are unaffected (they are already exact matches, ordering is irrelevant).
  • A tuneable weight for the two score components is exposed as a configuration property.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions