Skip to main content

Datasette plugin adding SQL functions for fuzzy text matching powered by RapidFuzz

Project description

datasette-rapidfuzz

Datasette plugin adding SQL functions for fuzzy text matching powered by RapidFuzz.

It complements datasette-jellyfish, which provides edit-distance and phonetic metrics (Levenshtein, Damerau-Levenshtein, Jaro, Jaro-Winkler, Soundex, Metaphone). RapidFuzz adds the token- and partial-ratio family — wratio, token_sort_ratio, token_set_ratio, partial_ratio — which tolerate word reordering and partial overlaps that a plain edit distance cannot express, on a fast C++ core. Use jellyfish for distance/phonetics, this for ratio-style scoring.

Installation

Install it into the same environment as Datasette:

datasette install datasette-rapidfuzz

Usage

This plugin registers five SQLite functions:

rapidfuzz_ratio(a, b)
rapidfuzz_partial_ratio(a, b)
rapidfuzz_token_sort_ratio(a, b)
rapidfuzz_token_set_ratio(a, b)
rapidfuzz_wratio(a, b)

Example:

select rapidfuzz_wratio('Candollea', 'Candollea 37') as score;

Returns:

95.0

Finding the closest matches

To rank rows by similarity to a search term, score each row and sort with order by score desc — the default ascending order returns the least similar rows first. The functions return null for a null input, and null sorts first when ascending, so a plain order by score tends to surface blank rows. Add distinct and filter out nulls to see the closest distinct values rather than repeated copies of the top hit:

select distinct
  name,
  rapidfuzz_wratio(name, 'Ginkgo') as score
from things
where name is not null
order by score desc
limit 20;

Fuzzy scoring is evaluated row-by-row by SQLite, so on large tables narrow the rows first (with a where clause) or fuzz against a deduplicated helper table:

create table distinct_names as select distinct name from things;

Finding near-duplicates (self-join)

Comparing a column against itself finds values that are similar but not identical — likely typos or spelling variants. A self-join is O(n²), so for anything but a small table you need to block: only compare values that share a cheap key. Blocking on the first two characters works well, because typos and variants almost always differ inside a word rather than at the start, so a variant still shares its opening letters — while two characters keep each block small:

with items as (
  select distinct name from things
  where name is not null and substr(name, 1, 2) = 'Ca'
),
pairs as (
  select a.name as a, b.name as b, rapidfuzz_wratio(a.name, b.name) as score
  from items a join items b on a.name < b.name
)
select a, b, score
from pairs
where score >= 90 and score < 100
order by score desc
limit 30;

a.name < b.name compares each pair once and skips self-pairs; score < 100 drops exact matches so only genuine variants remain. Swap the literal 'Ca' for :prefix to make it an interactive parameter in Datasette.

Blocking trades coverage for speed: a shorter key (substr(name, 1, 1)) casts a wider net but forms far more pairs, while a longer key is faster but misses variants that differ within the blocked prefix. Raise Datasette's limit for large blocks (--setting sql_time_limit_ms 30000).

To sweep a whole column in one query, move the block into the join and run it against a deduplicated, indexed helper table:

create table distinct_names as select distinct name from things;
create index idx_block on distinct_names (substr(name, 1, 2), name);

select a.name as a, b.name as b, rapidfuzz_wratio(a.name, b.name) as score
from distinct_names a join distinct_names b
  on substr(a.name, 1, 2) = substr(b.name, 1, 2) and a.name < b.name
where rapidfuzz_wratio(a.name, b.name) >= 90
  and rapidfuzz_wratio(a.name, b.name) < 100
order by score desc;

The index lets SQLite seek each block instead of forming the full cross product — the difference between a query that finishes in seconds and one that times out. Index a small helper table rather than the source table, so the main database stays untouched.

For developers

Clone this repository and install your local copy in editable mode, so your edits take effect without reinstalling:

pip install -e . --no-build-isolation

Run the tests:

python -m unittest discover

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

datasette_rapidfuzz-0.1.0.tar.gz (4.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

datasette_rapidfuzz-0.1.0-py3-none-any.whl (4.6 kB view details)

Uploaded Python 3

File details

Details for the file datasette_rapidfuzz-0.1.0.tar.gz.

File metadata

  • Download URL: datasette_rapidfuzz-0.1.0.tar.gz
  • Upload date:
  • Size: 4.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for datasette_rapidfuzz-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8a47c30e4477d3aa37466cbbfa996385d6955906cee33e9ab378ecc5f36894fa
MD5 c02617ecdb273a6868614992452b0cbb
BLAKE2b-256 17c27c8346d916aa2638e2d5e953557b38e9a54641cae4d50877037de660e255

See more details on using hashes here.

Provenance

The following attestation bundles were made for datasette_rapidfuzz-0.1.0.tar.gz:

Publisher: publish.yml on jwelby/datasette-rapidfuzz

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file datasette_rapidfuzz-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for datasette_rapidfuzz-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c30b71a63b77eebbe09db2405622957f1e40b0f24fa2233511af4b9246356e20
MD5 0b5c1718538a8f03ac6e246693b574f9
BLAKE2b-256 8ce94cbdd4d3e920d2426d14fa8f87ec9e5211f4db8d3b41c8dfae6f5d740f11

See more details on using hashes here.

Provenance

The following attestation bundles were made for datasette_rapidfuzz-0.1.0-py3-none-any.whl:

Publisher: publish.yml on jwelby/datasette-rapidfuzz

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page