Skip to content

fix(search): match combined "Title: Subtitle" author+title queries; page author lookups at max size#689

Open
rknall wants to merge 2 commits into
Listenarrs:canaryfrom
rknall:fix/author-title-search
Open

fix(search): match combined "Title: Subtitle" author+title queries; page author lookups at max size#689
rknall wants to merge 2 commits into
Listenarrs:canaryfrom
rknall:fix/author-title-search

Conversation

@rknall

@rknall rknall commented Jun 15, 2026

Copy link
Copy Markdown

Summary

Two related improvements to the author+title search path.

  1. Correctness — combined Title: Subtitle queries (the form Library Import emits) returned zero results. Audible splits a book name across Title + Subtitle; the filter required the query to be a substring of one field individually, so the combined string matched neither and every result was dropped.
  2. Performance — the author-catalogue pagination derived its page size from the result cap, so a small cap shrank pages to 10 items and prolific authors took many sequential Audible calls.

Changes

Changed

  • Author and author+title lookups now page at 50 (Audible's maximum page size) instead of min(50, max(10, candidateLimit)). The aggregation loop already fetches every page until the catalogue ends, so page size never affected which results are considered — only the number of round-trips. Result: ~4× fewer Audible requests (Elfie Donnelly author+title: 13 → 3), identical result set.

Fixed

  • Author+title search now matches combined Title: Subtitle queries. Matching normalizes punctuation/whitespace and also tests the combined Title Subtitle form, so a query like A Dance with Dragons: A Song of Ice and Fire, Book 5 (author George R.R. Martin) returns the book (0 → 2 in the de region) instead of nothing.

Testing

  • Manual verification against a live instance with real data:
    • The combined-title query returns the book (previously 0 results).
    • The Elfie Donnelly author+title search drops from 13 → 3 Audible requests with an unchanged result set.

Notes

  • Why the page size is hardcoded to 50 rather than derived from the cap: candidateLimit is a result-set bound (how many results we keep), while page size is a transport concern (items per HTTP round-trip). The loop deliberately aggregates all pages regardless of the cap, so page size has no effect on the result set — only on latency. The old formula's only effect was to make pages smaller when a caller passed a small cap (the Advanced search sends cap=5 → pageSize 10). 50 is the API maximum, any smaller value only adds round-trips, and no larger value is possible — so there is nothing worth making configurable.
  • Out of scope: region-specific result differences (the same query returning the book under de but not us) are a separate regional-search concern, not addressed here.

Roland Knall added 2 commits June 15, 2026 08:33
… search

The author+title search branch filtered the author's catalogue by requiring
the query to be a substring of a result's Title OR Subtitle individually.
Audible splits a book name across Title + Subtitle (e.g. Title="A Dance with
Dragons", Subtitle="A Song of Ice and Fire, Book 5"), while callers and
Library Import pass the combined "Title: Subtitle" string -- which matched
neither field, so every author result was filtered out (0 results).

Normalize punctuation/whitespace and also match the combined "Title Subtitle"
form. Verified: "A Dance with Dragons: A Song of Ice and Fire, Book 5" by
George R.R. Martin now returns the book (0 -> 2) in the de region.
The author and author+title aggregation loops derived their page size from
the result cap: `pageSize = Math.Min(50, Math.Max(10, candidateLimit))`.
That conflates two unrelated concerns:

  * candidateLimit is a *result-set* bound — how many results we ultimately
    keep/return to the caller.
  * page size is a *transport* concern — how many items we ask Audible for
    per HTTP round-trip.

The loop already aggregates *every* page until Audible returns a short page
(it deliberately does NOT stop at candidateLimit — see the surrounding
comment). So page size has no effect on which or how many items end up in the
aggregated set; it only changes how many sequential API calls that takes.

The old formula therefore had exactly one effect: when a caller passed a
small cap it made pages *smaller*. The Advanced search sends `cap=5`, which
drove pageSize down to 10, so a 127-item author catalogue (Elfie Donnelly)
was fetched in 13 sequential Audible calls instead of 3 — pure added latency,
no benefit.

Hardcoding 50 (Audible's maximum page size) is strictly better:
  * Fewer round-trips: ~ceil(N/50) instead of ~ceil(N/min(...)). Never more.
  * Identical results — same items aggregated, same final cap applied later.
  * No larger value is possible (50 is the API max) and any smaller value
    only adds latency, so there is no reason to make it configurable.

Measured: the Elfie Donnelly author+title search drops from 13 to 3 Audible
requests with an unchanged result set.
@rknall rknall requested a review from a team June 15, 2026 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant