mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 08:21:39 -06:00
1199e3cdd4
Field rules resolve each field from whichever provider ranks first for it, and nothing ever compared candidates to one another. A provider that matched the wrong book still won every field it led on, so a single record could carry a title from one book, a cover from a second and a subtitle from a third. The stock defaults make that the ordinary case rather than an unlucky one, since cover leads with Amazon while title and subtitle lead with Goodreads. Relevance scoring is what let those wrong matches in. A candidate survived on any score above zero, and token overlap counted stopwords, so "The Girl on the Train" scored against a query for "The Hobbit" on the strength of a shared "the". Substring matching ignored word boundaries as well, which is how "Ubik" matched "Rubik Cube Solutions". Drop stopwords from the query side, require a majority of the words that remain, match whole words only, and give the surviving floor a name. Then hold every candidate to an anchor before field rules ever see it. The anchor is the edition confirmed by the book's own ISBN when there is one, otherwise the candidate the query supports most strongly, with the title rule breaking ties because that is where the reader declares which provider decides identity. Agreement admits subtitle extensions, reordered words and translated editions, and rejects on a contradicting author, which is the only signal that separates a book from a companion volume that extends its title. Reject solely on positive evidence: a candidate with no title, or with no author to compare against, keeps the benefit of the doubt, and a lone provider is never second-guessed. Rejected candidates no longer contribute their provider ids either, which would otherwise pin the wrong book for every later refresh. Normalizing titles to [a-z0-9] emptied every title written in Japanese, Chinese, Russian or Greek. That scored two providers reporting an identical title as a disagreement, which under the new anchor would drop all but one of them in those libraries, and it had already denied the relevance gate any way to score them at all. Decompose instead, strip nonspacing marks so Soseki matches Sōseki, and keep letters of any script. Two sets of fixtures described different books per provider while testing something else entirely, field-rule precedence and metadata locking, and now describe one book so that they still test what they were written for. Closes #1023