DanLevy.net

Ricerca vettoriale semantica e altri argomenti per conquistare amici e amanti

L'intero panorama della ricerca: esatta, fuzzy, semantica, ibrida — e quando combinarle tutte.

La ricerca non è una cosa sola, e la ricerca semantica non sostituisce tutto il resto.

“Trova l’utente con email dan@example.com” e “trovami articoli sul debugging per un neo-ingegnere” vengono entrambi definiti ricerca, ma non hanno quasi nulla in comune come problemi di ingegneria. Il primo ha una risposta corretta e una ricerca su indice O(log n). Il secondo non ha una risposta corretta — solo rilevanza — e richiede la comprensione di linguaggio, intento e significato.

Gli ingegneri più persuasivi nelle decisioni sulla ricerca — quelli che vincono le discussioni e consegnano il sistema giusto — comprendono l’intero panorama. Sanno quale strumento usare e perché, e sanno spiegarlo con chiarezza.

Questo articolo copre il livello semantico: cosa fa davvero la ricerca vettoriale, quando vince e dove dovrebbe restare fuori dai piedi. La versione utile non è “incapsula tutto”. È sapere quando i vettori meritano di stare accanto alla ricerca lessicale, fuzzy e per corrispondenza esatta in un’architettura ibrida.

La metà lessicale e fuzzy del quadro — tsvector, pg_trgm, pg_search — è in Postgres Text Searching Guide 2026.


Termini a Colpo d’Occhio

Embedding — Un elenco denso di numeri in virgola mobile prodotto da un modello, che rappresenta un pezzo di testo (o immagine, audio, ecc.) come un punto in uno spazio ad alta dimensionalità. Contenuti semanticamente correlati finiscono vicini; contenuti non correlati finiscono lontani.

Ricerca lessicale — Ricerca basata su corrispondenze esatte di parole e token. Veloce, deterministica e corretta per termini noti. Non capisce sinonimi, parafrasi o equivalenti tra lingue diverse.

Ricerca semantica — Ricerca basata sul significato anziché sui token. Una query per “come gestisco i timeout” può corrispondere a un documento intitolato “configurazione dei retry policy” senza parole condivise, perché i loro embedding sono geometricamente vicini.

Vettore — Un elenco di numeri. Nel contesto della ricerca, l’output di un modello di embedding. La “ricerca vettoriale” trova i vettori più vicini a un vettore query misurando la distanza geometrica.

FTS (Full-Text Search) — La ricerca lessicale integrata di Postgres, basata su tsvector / tsquery. Tokenizza, applica lo stemming e indicizza il testo per query basate su parole chiave. Forte per la prosa e la ricerca per termini esatti; cieca al significato.

BM25 — Un algoritmo di ranking per la ricerca lessicale (usato da Elasticsearch, Qdrant e altri). Assegna un punteggio ai risultati in base alla frequenza dei termini, ponderata per la rarità del termine nel corpus. Migliore della semplice corrispondenza per parole chiave; resta comunque lessicale.

HNSW (Hierarchical Navigable Small World) — L’indice standard per la ricerca approssimata del vicino più prossimo nella ricerca vettoriale. Costruisce un grafo di prossimità stratificato per query di similarità veloci e ad alto recall. pgvector, Qdrant, Weaviate e la maggior parte degli altri lo utilizzano.

RRF (Reciprocal Rank Fusion) — Un algoritmo per fondere elenchi classificati provenienti da più sistemi di retrieval. Usa solo la posizione di ranking — nessuna normalizzazione dei punteggi necessaria. Un risultato che si posiziona in alto in entrambi gli elenchi FTS e vettoriale ottiene un punteggio combinato più forte di uno che domina solo uno dei due.


Cosa Fa Davvero la Ricerca Semantica

Gli embedding vettoriali convertono il testo (o immagini, audio, ecc.) in un elenco di numeri — un punto in uno spazio ad alta dimensionalità. Un modello di embedding è addestrato in modo che il testo semanticamente correlato finisca vicino in quello spazio. “Cane” e “canide” finiscono vicini. “Correre una maratona” e “eseguire uno script Python” finiscono lontani nonostante condividano una parola.

La ricerca di similarità in quello spazio trova documenti il cui significato è più vicino al significato della query, indipendentemente dalla sovrapposizione esatta delle parole.

Questo significa:

La ricerca lessicale (tsvector, pg_trgm) non può fare nulla di tutto questo. Opera su parole e caratteri, non sul significato. Gli strumenti non sono intercambiabili — risolvono problemi diversi.


Quando pgvector Vince

Costruire RAG. Retrieval-Augmented Generation recupera i chunk di documento il cui significato è più vicino alla domanda dell’utente, per poi passarli a un modello linguistico come contesto. Questo passaggio di retrieval è un’operazione vettoriale. FTS perderà parafrasi, sinonimi e corrispondenze concettuali che un chunk rilevante potrebbe esprimere in modo diverso. Il vantaggio di pgvector rispetto a un vector store autonomo: gira all’interno della tua istanza Postgres esistente — nessun servizio separato da distribuire, operare o su cui sincronizzare i dati.

Gli utenti descrivono cosa vogliono, non cosa cercare. “Articoli sulla costruzione della fiducia come nuovo manager” non ha parole chiave che appaiono in modo affidabile nei post pertinenti. “Un framework leggero per la gestione degli effetti collaterali” potrebbe non usare quelle parole esatte nella documentazione. La ricerca vettoriale corrisponde all’intento, non all’ortografia.

Trovare elementi simili. Prodotti correlati, ticket di supporto simili, segnalazioni di bug duplicati, articoli che potrebbero piacerti anche a te. “Trova issue simili a questa” è una ricerca del vicino più prossimo — incapsula l’elemento, trova i suoi vicini geometrici. Un avvertimento importante: la ricerca vettoriale restituirà sempre risultati, anche quando nulla è genuinamente simile. Per casi di deduplica e raccomandazione, filtra per una soglia minima di similarità (es. similarità cosine ≥ 0,80) per evitare di far emergere corrispondenze a bassa confidenza come se fossero significative.

Deduplicazione semantica. Prima di indicizzare contenuti per RAG o ricerca, spesso serve identificare quasi-duplicati nel corpus — articoli rivisitati più volte, ticket di supporto archiviati due volte, voci di knowledge base che si sovrappongono in modo significativo. Incapsula i documenti e filtra per similarità cosine per segnalare o unire quasi-duplicati prima che inquinino il tuo indice. Questo impedisce al retrieval di restituire più chunk quasi identici e diluire la finestra di contesto.

Ricerca multilingue. I modelli di embedding multilingue mappano contenuti semanticamente equivalenti tra lingue diverse in vettori vicini. Una query in spagnolo per “perder peso” può corrispondere a un articolo in inglese su “sustainable weight loss habits” — nessun token condiviso, stesso significato sottostante. FTS richiede configurazione di dizionari per lingua e gestisce male le query cross-lingua. pg_trgm è indipendente dalla lingua ma ortografico, non semantico.

Configurare pgvector

Dall’installazione dell’estensione alla query di similarità, la configurazione richiede poche istruzioni SQL:

CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE documents ADD COLUMN embedding vector(1536);
-- HNSW è di solito il primo indice da provare per dataset di dimensioni moderate
CREATE INDEX documents_embedding_idx
ON documents USING hnsw (embedding vector_cosine_ops);
-- Query di ricerca semantica
SELECT id, title, 1 - (embedding <=> $1::vector) AS similarity
FROM documents
ORDER BY embedding <=> $1::vector
LIMIT 10;

<=> è la distanza cosine. 1 - distanza_cosine dà la similarità cosine (1,0 = identico, 0,0 = ortogonale). Per ivfflat (l’alternativa più vecchia e più veloce da costruire), usa lists = sqrt(row_count) come punto di partenza.

Cosa pgvector Non Gestisce Bene


Ricerca Ibrida: Il Caso per Entrambe

La documentazione tecnica è l’esempio più chiaro in cui nessuno dei due strumenti basta da solo.

Gli utenti che cercano “come configurare i timeout” hanno bisogno di corrispondenza concettuale: un articolo intitolato “Impostazione di policy di retry e limiti di connessione” non ha parole chiave in comune ma è esattamente ciò che serve.

Gli stessi utenti cercano anche withRetry(), ECONNRESET e ERR_SOCKET_TIMEOUT. Queste stringhe esatte devono apparire — la corrispondenza semantica potrebbe non trovarle in modo affidabile e un falso positivo (concettualmente simile ma non l’API giusta) è attivamente fuorviante.

La ricerca vettoriale gestisce le query concettuali. FTS gestisce i termini esatti. Nessuno dei due gestisce bene entrambi da solo.

La soluzione è la ricerca ibrida: esegui entrambe e fondoni i risultati.

Reciprocal Rank Fusion

Reciprocal Rank Fusion (RRF) è l’algoritmo standard per combinare elenchi classificati provenienti da diversi sistemi di retrieval. Non richiede la normalizzazione dei punteggi tra i sistemi — usa solo le posizioni di ranking. Un risultato che appare in alto in entrambi gli elenchi ottiene un punteggio combinato più forte di uno che domina solo uno.

WITH fts_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, query) DESC) AS rank
FROM documents, to_tsquery('english', $1) query
WHERE search_vector @@ query
LIMIT 50
),
vector_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank
FROM documents
ORDER BY embedding <=> $2::vector
LIMIT 50
),
rrf AS (
SELECT
COALESCE(f.id, v.id) AS id,
COALESCE(1.0 / (60 + f.rank), 0) +
COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score
FROM fts_results f
FULL OUTER JOIN vector_results v ON f.id = v.id
)
SELECT d.id, d.title, rrf.rrf_score
FROM rrf
JOIN documents d ON d.id = rrf.id
ORDER BY rrf_score DESC
LIMIT 10;

Il 60 al denominatore è la costante RRF. Valori più alti smorzano le differenze di posizione; valori più bassi le amplificano. Il default di 60 funziona bene per la maggior parte dei tipi di contenuto.

RRF evita il problema più difficile di normalizzare ts_rank (un punteggio log-frequenza) rispetto alla distanza cosine (una misura geometrica). Non sono confrontabili. RRF chiede solo: “quanto in alto è apparso questo risultato in ciascun elenco?”

Ricerca Ibrida con Trigrammi Anche

Per la ricerca lato utente su contenuti misti — dove gli utenti potrebbero cercare un nome di persona, un concetto o un termine esatto nella stessa sessione — la fusione a tre vie gestisce tutto:

WITH trgm_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY similarity(title, $1) DESC) AS rank
FROM documents
WHERE title % $1
LIMIT 50
),
fts_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, to_tsquery('english', $1)) DESC) AS rank
FROM documents
WHERE search_vector @@ to_tsquery('english', $1)
LIMIT 50
),
vector_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank
FROM documents
ORDER BY embedding <=> $2::vector
LIMIT 50
),
rrf AS (
SELECT
COALESCE(t.id, f.id, v.id) AS id,
COALESCE(1.0 / (60 + t.rank), 0) +
COALESCE(1.0 / (60 + f.rank), 0) +
COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score
FROM trgm_results t
FULL OUTER JOIN fts_results f ON t.id = f.id
FULL OUTER JOIN vector_results v ON COALESCE(t.id, f.id) = v.id
)
SELECT d.id, d.title, rrf.rrf_score
FROM rrf
JOIN documents d ON d.id = rrf.id
ORDER BY rrf_score DESC
LIMIT 10;

Questo gestisce: corrispondenze fuzzy di nomi (trigrammi), corrispondenze esatte di parole chiave (FTS) e query concettuali (vettoriale). Una singola casella di ricerca può servire tutti e tre gli intenti dell’utente.


Architetture Ibride Multi-Livello

Le applicazioni reali raramente hanno una singola superficie di ricerca. Ne hanno multiple, ognuna con un bisogno diverso:

SuperficieCosa cercano gli utentiLivelli consigliati
Ricerca blog / documentazioneParole chiave + concettiFTS + pgvector (RRF)
Ricerca nomi utenti/clientiNomi con errori di battiturapg_trgm
Ricerca prodottiNomi, descrizioni, “simile a”pg_trgm + FTS + pgvector
Deduplica ticket supporto”Issue simili a questa”Solo pgvector
Ricerca SKU/ordini internaIdentificatori esattiIndice B-tree
RAG su knowledge base ampiaDomande in linguaggio naturalepgvector (documenti chunked)
E-commerce “potrebbe piacerti anche”Similarità comportamentale + semanticapgvector
AutocompletamentoPrefisso, tollerante agli erroripg_trgm

Questi non sono ipotetici. La maggior parte delle applicazioni content-heavy ha bisogno di almeno due superfici di ricerca distinte con forme di query diverse. La tentazione è scegliere un approccio e usarlo ovunque — di solito la ricerca vettoriale ora, dato che è la scelta di moda. Questo porta a embedding costosi per problemi dove un indice trigramma sarebbe stato più veloce, più economico e più corretto.

La Regola Pratica

Aggiungi un livello quando appare un modo di fallire che il livello corrente non può risolvere:


Se Hai Davvero Bisogno di un Vector Store Dedicato

pgvector gestisce molta ricerca applicativa prima che tu abbia bisogno di un altro database. Il punto di taglio approssimativo dipende dal conteggio dei vettori, dalle impostazioni dell’indice, dalla frequenza di scrittura, dai filtri, dall’hardware e dalla concorrenza, quindi tratta qualsiasi regola “sotto 10M di vettori” come un’assunzione di partenza da verificare con benchmark, non come un limite del prodotto. Quando lo superi davvero — concorrenza molto alta, requisiti di latenza p99 molto bassi, miliardi di vettori o serie esigenze di isolamento multi-tenant — il panorama dei database vettoriali dedicati è ampio e vale la pena capirlo.

Cosa Significano Davvero le Colonne della Matrice

Ricerca ibrida significa che la ricerca per parole chiave BM25 e la similarità vettoriale girano in un’unica query, fuse tramite RRF. Senza di essa, o scegli una modalità di ricerca o fondi due query tu stesso.

Vettori sparsi vanno oltre BM25. Un vettore SPLADE sparso ha ~30.000 dimensioni (una per termine del vocabolario), ~98% zeri. Le posizioni non nulle ti dicono quali termini contano e quanto. Una query per “cani” pesa anche “canide” e “animale domestico” — precisione a livello BM25 più espansione dei termini all’interno di un indice vettoriale. Se questa colonna è falsa, hai bisogno di un layer FTS separato per le query per termini esatti.

# SPLADE: ~30.000 dim, ~60 non nulle — si attivano solo le posizioni del vocabolario rilevante
def encode_splade(text: str) -> dict:
tokens = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
with torch.no_grad():
output = model(**tokens)
vec = torch.log1p(torch.relu(output.logits)).max(dim=1).values.squeeze()
return {"indices": vec.nonzero().squeeze().tolist(), "values": vec[vec != 0].tolist()}

SQL / SQL-like riguarda davvero il filtraggio. La ricerca vettoriale senza filtraggio è una demo. Servono ancora scope del tenant, intervalli di date, permessi e filtri per categoria. SQL completo (pgvector, LanceDB) lo esprime accanto ai tuoi join esistenti. I database purpose-built usano oggetti filtro JSON (Qdrant, Pinecone), un DSL di query (Elasticsearch, Milvus) o GraphQL (Weaviate). Funzionano; SQL diventa più attraente man mano che la logica di filtraggio si fa complessa.

-- pgvector: la similarità vettoriale è solo un'altra espressione
SELECT id, title, 1 - (embedding <=> $1) AS score
FROM documents
WHERE tenant_id = $2
AND category = ANY($3::text[])
AND created_at > NOW() - INTERVAL '90 days'
ORDER BY embedding <=> $1
LIMIT 10;
# Qdrant: filtro equivalente come oggetto Python — stesso risultato, più cerimonie
results = client.query_points(
collection_name="documents", query=query_embedding,
query_filter=models.Filter(must=[
models.FieldCondition(key="tenant_id", match=models.MatchValue(value=tenant_id)),
models.FieldCondition(key="category", match=models.MatchAny(any=categories)),
models.FieldCondition(key="created_at", range=models.DatetimeRange(gte=cutoff)),
]),
limit=10,
)

Multimodale nativo significa che il database include modelli di embedding per contenuti non testuali. Gli passi un URL di immagine grezzo; lui gestisce la vettorializzazione. La maggior parte dei database sono agnostici rispetto all’embedding — possiedi tu la pipeline di embedding. Marqo e Weaviate (tramite moduli CLIP/ImageBind) chiudono questo ciclo.

# Marqo: POST di immagini grezze, query con testo — nessun passaggio di embedding esterno
mq.index("products").add_documents(
[{"id": "shoe-001", "image": "https://cdn.example.com/shoes/001.jpg"}],
tensor_fields=["image"]
)
results = mq.index("products").search(q="scarpe leggere per l'estate")
# Restituisce shoe-001 nonostante zero sovrapposizione di parole chiave — CLIP gestisce la corrispondenza cross-modale

Indice su disco è una leva di costo. Gli indici HNSW in RAM possono richiedere diversi GB di RAM per milione di vettori a 1536 dimensioni una volta contati vettori grezzi, grafo overhead e metadati. Le alternative disk-native (Milvus DiskANN, Elasticsearch DiskBBQ, formato Lance di LanceDB, tier object storage di Turbopuffer) spesso scambiano un po’ di latenza di query per un costo infrastrutturale inferiore. Per carichi RAG dove la latenza del modello domina già, quel compromesso vale spesso la pena di essere benchmarkato.

Dimensioni massime è una migrazione nascosta nella tua architettura. text-embedding-3-large usa 3072 dimensioni, Jina v3 può emettere embedding più grandi e i modelli di ricerca continuano a spingere verso l’alto. Alcuni servizi gestiti pubblicano limiti rigidi sulle dimensioni; altri documentano limiti alti o nessun limite pratico per i modelli di embedding tipici. Controlla la documentazione attuale prima di impegnarti. Scegli qualcosa con margine; migrare un indice vettoriale perché hai raggiunto un soffitto dimensionale è uno sprint doloroso.

Ultima verifica contro la documentazione pubblica e le pagine prodotto l’8 maggio 2026. Tratta la tabella qui sotto come un aiuto decisionale, non come un sostituto per il controllo di limiti attuali, prezzi e feature flag dei servizi gestiti.

Il Panorama

DatabaseDistribuzioneLicenzaRicerca IbridaVettori SparsiSQL / SQL-likeMultimodaleIndice DiscoDim MassimeSweet Spot
pgvectorSelf-host / managed (Supabase, Neon, RDS)OSS (PostgreSQL)Manuale (RRF via SQL)✅ SQL completo✅ HNSW su disco16.000 storage; 2.000 indicizzati vectorGià su Postgres; conteggi vettoriali moderati
QdrantSelf-host / CloudApache 2.0✅ BM25 nativo✅ Supporto maturo❌ (REST/gRPC)65.535Query filtrate su larga scala; metadati complessi
WeaviateSelf-host / CloudBSD 3✅ BM25 nativo + RRF❌ (GraphQL / gRPC)✅ tramite moduli65.535Pattern di accesso GraphQL; vettorializzazione integrata
PineconeSolo CloudProprietaria✅ (aggiunta 2024)✅ (serverless)20.000Semplicità gestita; nessun team ops
Milvus / ZillizSelf-host / Cloud (Zilliz)Apache 2.0✅ Nativo✅ SQL-like (Milvus Query Language)✅ DiskANN32.768Scala miliardaria; enterprise on-prem
ChromaEmbedded / self-hostApache 2.065.535Solo sviluppo locale e prototipazione
LanceDBEmbedded / CloudApache 2.0✅ SQL tramite DataFusion✅ Nativo✅ (formato Lance)IllimitateEdge / serverless; lakehouse multimodale
OramaEmbedded / CloudApache 2.0✅ Full-text + vettorialeVariaApp JS/edge; ricerca leggera per siti/app
TurbopufferSolo Cloud (serverless)Proprietaria✅ BM25 + vettoriale✅ (object storage)16.000SaaS multi-tenant; milioni di namespace
ElasticsearchSelf-host / Elastic CloudSSPL / AGPLv3✅ RRF + ELSER sparso✅ (ELSER)✅ Query DSL✅ DiskBBQ4.096Già su stack Elastic; ricerca ibrida enterprise
OpenSearchSelf-host / AWS managedApache 2.0✅ RRF + Neural Search✅ Query DSL✅ FAISS + HNSW16.000AWS-native; alternativa Elastic open-source
VespaSelf-host / CloudApache 2.0✅ Nativo✅ Tensori / ranking lessicale✅ YQL✅ TensoriEffettivamente illimitatoRicerca + ranking + sistemi di raccomandazione
ClickHouseSelf-host / CloudApache 2.0Manuale✅ SQL completo✅ Colonnare + HNSWVariaAnalytics/log con ricerca vettoriale accanto a OLAP
MongoDB AtlasCloud / self-hostSSPL✅ Integrata✅ MQL + aggregation✅ HNSW8.192Già su MongoDB; documento + vettore in uno
Redis (VSS)Self-host / Redis CloudRSALv2 / SSPL✅ (RediSearch)❌ Solo RAM32.768Latenza ultra-bassa; ricerca vettoriale a livello cache
MarqoCloud / self-hostApache 2.0✅ Focus nativoVariaMultimodale end-to-end: immagine + testo + video

Alcune Cose Che Non Entrano nella Tabella

Multi-tenancy di Turbopuffer è costruita attorno a un numero molto elevato di namespace. Il suo posizionamento pubblico e le storie dei clienti enfatizzano carichi di lavoro come il corpus grande e pesante di namespace di Notion. Se ogni utente o organizzazione ha bisogno di ricerca vettoriale isolata, quell’architettura può cambiare l’economia, ma fai comunque benchmark sulla tua forma di tenant.

Modalità embedded di LanceDB è la cosa più vicina a “SQLite per la ricerca vettoriale.” Gira in-process, non richiede server e funziona in Lambda, Cloudflare Workers e ambienti edge. Il formato colonnare Lance rende l’operazione embedded pratica a scala reale.

Chroma è più forte nello sviluppo/test e in piccole distribuzioni app. Se punti a corpus molto grandi, HA, operazioni disk-heavy o ricerca ibrida di prima classe, valuta uno store orientato alla produzione prima di promuovere il prototipo in infrastruttura.

Vespa è ciò a cui ti rivolgi quando il retrieval è solo metà del prodotto. Combina retrieval lessicale, ricerca del vicino più prossimo, tensori, espressioni di ranking, raggruppamento e serving online. Quel potere è reale, ma anche la complessità operativa e di modellazione. Si adatta a team di ricerca/raccomandazione più che ad “aggiungi ricerca semantica alla mia app CRUD.”

ClickHouse appartiene alla conversazione quando la ricerca è attaccata all’analytics. Se la tua fonte di verità sono eventi, log, trace o metriche, ClickHouse tiene distanza vettoriale, filtraggio, aggregazione e serio full-text indexing in un unico motore SQL. Non è un database vettoriale purpose-built, ma spesso è la risposta noiosa-giusta per il retrieval analitico.

I vettori sparsi sono il modo per ottenere corrispondenza per parole chiave di qualità BM25 all’interno di un indice vettoriale — senza eseguire un motore full-text separato. Qdrant ed Elasticsearch hanno implementazioni particolarmente mature qui. Se la ricerca ibrida è critica e un’architettura a due sistemi è un ostacolo insormontabile, il supporto ai vettori sparsi è ciò che cercare.

Scegliere Quando Hai Superato pgvector


L’Unica Cosa da Non Fare

Non usare la ricerca vettoriale come ricerca fuzzy per cose che hanno risposte corrette.

“Trovami l’utente con email dan@example.com” non è un problema di ricerca vettoriale. “Trova l’ordine con ID ORD-12345” non lo è neanche. Incapsulare ORD-12345 e cercare per similarità cosine restituirà qualcosa — ma potrebbe essere sbagliato. Un identificatore ha una risposta corretta. Una corrispondenza approssimata su un identificatore è un bug.

La ricerca vettoriale restituisce la cosa più simile nel tuo dataset, anche quando nulla è davvero rilevante. Non sa quando non esiste una buona risposta. Va bene per documenti correlati. È un problema serio per la ricerca di record esatti, dove una risposta sbagliata ma sicura è peggio di un risultato vuoto.

Lo stesso vale nella direzione opposta: non usare FTS per query in cui l’utente sta descrivendo un concetto. “articoli su come prendere decisioni difficili in condizioni di incertezza” non contiene parole chiave affidabili. FTS restituirà rumore o nulla. Usa lo strumento giusto per la forma della query.


Il Quadro Completo

La maggior parte dei sistemi di ricerca in produzione ha bisogno di più di un livello:

Questi non sono strumenti in competizione. Sono complementari. Un sistema di ricerca ben progettato sceglie il livello giusto per ogni forma di query — e quando le forme di query si sovrappongono, esegue più livelli e fonde i risultati.

I team che consegnano buone funzionalità di ricerca comprendono l’intero stack. Quelli che non lo fanno prendono un database vettoriale, incapsulano tutto e si chiedono perché le ricerche esatte a volte restituiscano il record sbagliato.