Fuzzy Search
Also Fuzzy Prefix Search
Fuzzy (prefix) search finds all words y of a dictionary D with ED(x, y) ≤ δ (or PED(x, y) ≤ δ) for a possibly misspelled (and incomplete) query x, by filtering candidates with a q-gram index and verifying only the survivors.
Formula#
Filter-then-verify algorithm (fuzzy prefix search, fixed ):
- Pad with
$on the left (see Q-Gram > Padding) and compute its q-grams; with left-only padding . - Fetch the inverted list of each q-gram from the Q-Gram Index, merge them, and count for each word how often it occurs: this is .
- Filter with the q-gram lemma, Corollary 2: keep only words with
- Verify: compute only for the survivors (with the column cut-off) and return those with .
For fuzzy search (ED), pad on both sides and filter with (Corollary 1).
def fuzzy_prefix_search(x, index, q, delta=1):
x_padded = "$" * (q - 1) + x
counts = {}
for i in range(len(x_padded) - q + 1):
qgram = x_padded[i:i + q]
for word_id in index.get(qgram, []):
counts[word_id] = counts.get(word_id, 0) + 1
threshold = len(x_padded) - q + 1 - q * delta # = |Q_q(x)| - q * delta = |x| - q * delta
return [word_id for word_id, count in counts.items()
if count >= threshold] # candidates; verify each with PED
Properties#
- Two challenges (as for keyword search in Lectures 1–2): a model of relevance, here (P)ED, and an index that finds the matches fast, here the q-gram index.
- Linear scan (compute (P)ED for every , as
grep/agrepdo) takes time linear in : fine for medium-sized, too slow for large dictionaries. - Correctness: the filter has no false negatives, because every match satisfies the bound of the q-gram lemma. If the threshold is , words not in any fetched list must be verified as well.
- Running time of the filter phase is linear in the total length of the fetched inverted lists, typically much smaller than verifying every word.
- Dictionary origins: popular queries from a query log (basis of query suggestions), words and common phrases of a text collection, entities of a knowledge graph (ES8: 1,736,613 Wikidata entities with popularity and synonyms).
- Application: context-sensitive autocompletion of entity names when writing SPARQL queries (QLever UI, see SPARQL and Knowledge Graphs); in ES9/ES10 the fuzzy prefix search becomes the backend of a search-as-you-type web app.
Example#
Exam WS 18/19, Task 3.2: index over abba (1), bab (2), aba (3), , one $ on the left; query , .
$aaab→ 2-grams$a,aa,aa,ab, so .$a→ {1, 3},aa→ (no list),ab→ {1, 2, 3}: counts abba 2, bab 1, aba 2.- Threshold : candidates abba, aba.
- , : no word matches.
Sources#
- Slides 08, p. 5 (problem), p. 6 (dictionaries), p. 7 (linear scan), p. 21 (filter algorithms), pp. 25–26 (with the q-gram index)
- Slides 07, p. 26 (autocompletion in QLever)
- DBIS_VL08 > Problem setting, DBIS_VL08 > Simple solution: linear scan, DBIS_VL08 > Filter algorithms, DBIS_VL08 > Using the index
- Exams: DBIS Exam WS1819 (not published) (Tasks 3.2, 3.3), DBIS Exam WS2324 (not published) (Task 4)