Come funzionano i Motori di Ricerca: Guida Tecnica da Lucene a Elasticsearch

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Come funzionano i Motori di Ricerca

Hai presente quando digiti tre lettere sbilenche sulla tastiera e Google sembra leggerti nel pensiero prima ancora di premere invio?

Spoiler: non è magia..

È una combinazione di matematica, strutture dati, linguistica computazionale e architetture distribuite.

Dietro quel millisecondo di attesa si nasconde un’architettura brutale e bellissima, capace di setacciare miliardi di documenti senza fare una piega.

Se ti sei mai chiesto come faccia un software a “capire” cosa cerchi tra montagne di dati disordinati, sei nel posto giusto.

Andremo ad analizzare i componenti del motore, pezzo dopo pezzo: partiremo dalle basi di Apache Lucene per arrivare ai sistemi che oggi alimentano l’intelligenza artificiale, includendo del codice Python per testare subito i concetti in prima persona.

E per capire davvero come funziona tutto questo, più avanti ti racconterò una micro‑storia concreta: cosa succede quando cerchi “pizza” alle 23:00. È lì che la teoria diventa realtà.

Pubblicità

Cos’è (davvero) un motore di ricerca

Un motore di ricerca non è un archivio, ma un sistema dinamico che compie tre passi fondamentali:

  1. Raccoglie i dati (Crawling): Esplora il web tramite bot che saltano da un link all’altro.

  2. Li organizza (Indexing): Trasforma il caos dei siti web in una struttura ordinata e interrogabile.

  3. Risponde alle query (Ranking): Decide quali risultati meritano la prima pagina e quali il dimenticatoio.

Crawling: costruire la mappa del web

Il crawling è il processo con cui il motore di ricerca crea il suo “web interno”. I crawler (o bot) visitano le pagine, seguono i collegamenti e raccolgono i contenuti. È un lavoro mastodontico: si tratta di costruire e aggiornare costantemente una copia gigantesca di internet.

Indexing: il cuore pulsante (Inverted Index)

Una volta raccolti i dati, bisogna organizzarli. Immagina di dover cercare una parola in un libro: non leggi tutto il libro ogni volta, ma vai all’indice analitico alla fine.

Il motore di ricerca fa esattamente questo usando l’Inverted Index (Indice Inverso). Invece di memorizzare:

  • Documento → Parole contenute

Memorizza:

  • Parola → Lista dei documenti in cui appare

Esempio:

  • “AI” → doc1, doc3, doc7

  • “Marketing” → doc2, doc3

Questo trasforma una ricerca potenzialmente infinita in un’operazione istantanea.

Il motore sotto il cofano: Apache Lucene

Quando parliamo di ricerca moderna, il nome che domina la scena non è Elasticsearch o Solr, ma quello che c’è dentro di loro: Apache Lucene.

Lucene è una libreria open-source in Java che rappresenta il vero standard di mercato. Per usare una metafora:

  • 👉 Lucene è il motore a scoppio.

  • 👉 Elasticsearch e Apache Solr sono le automobili (con carrozzeria, sedili e cruscotto).

Cosa rende Lucene così potente?

  1. Analisi avanzata del testo: Prima di finire nell’indice, il testo passa attraverso una pipeline di normalizzazione:

    • Tokenizzazione: divide le frasi in singole parole.

    • Stemming e Lemmatizzazione: riduce le parole alla loro radice (es. “correndo” diventa “corr”).

    • Rimozione Stop Words: elimina termini inutili come “il”, “lo”, “di”.

    • Gestione Sinonimi: capisce che se cerchi “auto” ti interessano anche i risultati per “macchina”.

  2. Segmenti e Merging: Lucene non riscrive l’intero indice a ogni aggiornamento. Crea piccoli segmenti che poi unisce in background. Questo permette di avere ricerche velocissime anche mentre il sistema sta aggiungendo nuovi dati.

  3. Ranking: come decide cosa è rilevante

    Trovare i documenti è solo metà del lavoro. La vera sfida è ordinarli. Lucene ha guidato l’evoluzione da un sistema matematico semplice a uno decisamente più “furbo”.

    Dal TF-IDF al BM25: la fine dell’abbuffata di keyword

    Per anni il re è stato il TF-IDF (Term Frequency-Inverse Document Frequency). Era un sistema logico ma “ingenuo”: più volte scrivevi una parola, più il documento saliva in classifica. Il problema? Favoriva spudoratamente i documenti lunghissimi. Se un blog post di 5.000 parole ripeteva “marketing” 50 volte, batteva una guida perfetta di 500 parole che lo citava solo 5, semplicemente per “massa critica”.

    Oggi lo standard è il BM25 (Best Matching 25), che introduce due correzioni fondamentali:

    • Saturazione della Frequenza: Il BM25 capisce che il valore di una parola non cresce all’infinito. Se hai citato “AI” 3 o 4 volte, abbiamo capito che il testo parla di quello. Citarlo 40 volte non rende il documento 10 volte più rilevante. Il punteggio “satura”: dopo una certa soglia, ripetere la keyword non serve più a nulla.

    • Normalizzazione della Lunghezza: Il motore ora “penalizza” i documenti troppo prolissi che diluiscono il contenuto e premia quelli brevi e densi di informazioni.

    In breve: Il BM25 è il motivo per cui oggi il keyword stuffing (riempire una pagina di parole chiave a caso) non solo non funziona più, ma è diventato controproducente.

La Nuova Frontiera: Vector Search

Nelle versioni più recenti (Lucene 9+), il motore ha integrato la Vector Search. Grazie ad algoritmi come KNN (K-Nearest Neighbors) e HNSW, oggi i motori di ricerca possono trovare risultati basandosi sul significato e non solo sulle parole esatte. È il ponte che collega la ricerca classica all’Intelligenza Artificiale Generativa.

Lo sapevi?

Google non usa più solo il testo. Con la Vector Search, il tuo motore può trovare “Pizzerie” anche se nel sito c’è scritto solo “Specialisti dell’impasto napoletano”, perché capisce che i due concetti sono vicini nello spazio vettoriale.


Mettiamoci alla prova: Mini motore di ricerca in Python

Ecco un esempio pratico che puoi eseguire su Google Colab per capire come funziona un “mini-Lucene”.

Forse potrebbe interessarti anche:  Guida a Pytrends in Python: estrarre dati da Google Trends e gestire l'errore 429

📌 Cosa fa questo codice

  • costruisce un inverted index
  • calcola un ranking (TF-IDF semplificato)
  • risponde a una query

STEP 1 — Dataset

documents = {
    1: "Il marketing digitale usa intelligenza artificiale",
    2: "La SEO è fondamentale nel marketing online",
    3: "L'intelligenza artificiale sta rivoluzionando il digital marketing",
    4: "Python è usato per data science e machine learning",
    5: "Il machine learning è alla base dell'intelligenza artificiale"
}

STEP 2 — Tokenizzazione

import re

def tokenize(text):
    return re.findall(r'\b\w+\b', text.lower())

STEP 3 — Inverted Index

from collections import defaultdict

inverted_index = defaultdict(list)

for doc_id, text in documents.items():
    tokens = set(tokenize(text))  # set = evita duplicati
    for token in tokens:
        inverted_index[token].append(doc_id)

# Visualizza indice
for term, docs in list(inverted_index.items())[:10]:
    print(term, "->", docs)
il -> [1, 3, 5]
digitale -> [1]
marketing -> [1, 2, 3]
usa -> [1]
artificiale -> [1, 3, 5]
intelligenza -> [1, 3, 5]
seo -> [2]
fondamentale -> [2]
è -> [2, 4, 5]
online -> [2]

STEP 4 — TF-IDF (semplice)

import math

def compute_tfidf(query_tokens, documents):
    scores = {}
    N = len(documents)

    for doc_id, text in documents.items():
        tokens = tokenize(text)
        score = 0

        for term in query_tokens:
            tf = tokens.count(term) / len(tokens)

            df = sum(1 for d in documents.values() if term in tokenize(d))
            idf = math.log(N / (df + 1))

            score += tf * idf

        scores[doc_id] = score

    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

STEP 5 — Query

query = "intelligenza artificiale marketing"
query_tokens = tokenize(query)

results = compute_tfidf(query_tokens, documents)

print("Risultati ordinati per rilevanza:\n")
for doc_id, score in results:
    print(f"Doc {doc_id} (score={score:.4f}): {documents[doc_id]}")

OUTPUT (interpretazione)

Vedrai che:

  • i documenti con più match rilevanti salgono
  • quelli meno pertinenti scendono

👉 Esattamente come fa Elasticsearch (ma in versione molto semplificata)


Risultati ordinati per rilevanza:

Doc 1 (score=0.1116): Il marketing digitale usa intelligenza artificiale
Doc 3 (score=0.0837): L'intelligenza artificiale sta rivoluzionando il digital marketing
Doc 5 (score=0.0496): Il machine learning è alla base dell'intelligenza artificiale
Doc 2 (score=0.0319): La SEO è fondamentale nel marketing online
Doc 4 (score=0.0000): Python è usato per data science e machine learning

Cosa abbiamo appena costruito

Abbiamo creato:

Forse potrebbe interessarti anche:  Il Quartetto di Anscombe: Perché Devi SEMPRE Visualizzare i Tuoi Dati (Statistiche Identiche, Storie Diverse)

✅ inverted index
✅ ranking TF-IDF
✅ query engine

👉 In pratica una versione base di:

  • Apache Lucene
  • Elasticsearch

Perché questo esercizio è interessante? 

Molti pensano che un motore di ricerca faccia un gigantesco “Ctrl+F” su tutti i file del mondo. Questo esercizio dimostra perché non è così e rivela tre peculiarità fondamentali:

A. L’abbattimento della complessità (Il “miracolo” dell’indice)

Senza l’indice inverso, per ogni ricerca dovresti rileggere ogni singola parola di ogni documento. Se il web fosse un libro, l’indice inverso è l’indice analitico alla fine. Questo codice ti mostra che la ricerca moderna è una questione di strutture dati, non di potenza bruta di calcolo.

B. L’intelligenza statistica (Il peso del silenzio)

L’esercizio è affascinante perché introduce il concetto di rilevanza. Usando il logaritmo nell’IDF, il codice “capisce” implicitamente quali parole portano informazione e quali sono solo rumore grammaticale. È l’inizio della linguistica computazionale: trattare le parole come vettori numerici.

C. La modularità (L’architettura a pipeline)

Nota come le funzioni siano separate: tokenize -> index -> compute_tfidf. Nella realtà applicativa, questo ti permette di cambiare un pezzo senza rompere tutto. Vuoi supportare i sinonimi? Modifichi solo tokenize. Vuoi usare il BM25 (come suggerito prima)? Modifichi solo la formula dentro compute_tfidf.

Peculiarità: Questo script è il “DNA” di Elasticsearch. Se capisci queste 40 righe, hai capito l’80% della logica che governa il recupero delle informazioni (Information Retrieval) a livello globale. Hai costruito un sistema che non si limita a “trovare”, ma “valuta”.


Google e la tua Pizza 🍕

Ore 23:00: Missione Pizza

Sono le undici di sera. Sei sul divano, apri Google e digiti: “pizza”. Mentre il tuo dito si stacca dal tasto Invio, nel data center sta scoppiando una “guerra” di dati. Ecco cosa succede:

Forse potrebbe interessarti anche:  Intelligenza Artificiale applicata al teorema di Bayes: un esempio in Python

1. Il Risveglio dei Giganti (Retrieval)

In un battito di ciglia, Google interroga l’Inverso Index (quello che abbiamo visto nel codice Python). Invece di leggere tutto il web, va dritto alla cartella “Pizza”.

  • Il problema: La cartella contiene miliardi di documenti. Ricette, storia della pizza, siti di pizzerie a New York, Wikipedia.

  • L’Azione: Il motore estrae tutti i candidati. È un set enorme e disordinato.

2. Il Filtro della Realtà (Contextual Awareness)

Qui il software smette di essere un bibliotecario e diventa un assistente personale. Entrano in gioco i segnali di contesto:

  • Geolocalizzazione: “L’utente è a Milano, zona Navigli”. Cestinati i risultati di Napoli e Roma.

  • Il Fattore Tempo: Sono le 23:00. Il motore controlla gli orari di apertura (grazie ai dati strutturati). Cestinate le pizzerie che chiudono alle 22:00.

3. La Sfida di Ranking (BM25 + AI)

Rimangono un centinaio di pizzerie aperte e vicine. Come decidere chi sta in prima posizione?

  • BM25 (Evoluto): Chi ha la parola “pizza” nel titolo? Chi ha recensioni che citano spesso “consegna rapida”?

  • Intent Understanding: Google sa che alle 23:00 non vuoi studiare la fermentazione del lievito madre (intento informativo). Vuoi mangiare (intento transazionale). Quindi, declassa i blog di cucina e spinge in alto Google Maps e JustEat.

4. Il Lieto Fine

In 0.40 secondi, la pagina si carica. Non vedi la voce “Pizza” su Wikipedia. Vedi una mappa con tre puntini rossi a meno di 1 km da te, il tasto “Chiama” e il menu aggiornato.


Questa micro-storia ci insegna che un motore di ricerca moderno non è solo un “trovatore di parole”, ma un motore di probabilità:

  1. Non cerca “Pizza”: Cerca la soluzione più probabile al tuo problema di fame notturna.

  2. Usa il tempo come dato: Se cercassi “pizza” alle 10:00 del mattino, i risultati potrebbero essere diversi (forse ricette o corsi di cucina).

  3. Il codice è vivo: Quell’esercizio in Python che abbiamo fatto è lo scheletro, ma il contesto (ora, luogo, intento) è la carne che rende il sistema “intelligente”.

In pratica: Google ha appena usato la matematica per evitare che tu rimanga a stomaco vuoto.

Pubblicità