Filtrado y búsqueda de texto completo
1) Por qué se necesita una capa de búsqueda
El filtrado y la búsqueda de texto completo (FTS, Complete Text Search) proporcionan acceso rápido a los datos «por sentido», no solo a través de las claves primarias. La capa de búsqueda correctamente diseñada combina:- Filtros estrictos (categorías, fechas, precios, derechos de acceso)
- Texto completo (partido léxico y clasificación)
- Facetas (agregados para la navegación)
- Clasificación híbrida (BM25/TF-IDF + embeddings vectoriales)
- Protocolos fiables (paginación con cursores, TTL de tokens, charding cruzado)
2) Pintura arquitectónica
Componentes:1. Ingest/ETL → normalización, deduplicación, enriquecimiento, construcción de campos para el índice.
2. Indexador → índice inverso (lexemas → documentos), estructuras de columna, índice vectorial (HNSW/IVF-PQ).
3. Query Layer → parser de consultas, aplicación de filtros/derechos de acceso, programador de chards, k-way merge.
4. Ranker → BM25 + (opz.) LTR/Neural re-rank.
5. Serving → caché, cursores, facetas, highlites, autocompletar.
6. Observabilidad → métricas de latencia, calidad, experimentos A/B.
3) Modelo de datos e índice
3. 1 Campos y analizadores
Tipos: keyword (coincidencia plana), text (analizado), numeric/date/geo, vector.
Analizadores: tokenización, normalización (lowercase, Unicode NFKC), filtros (stop-word, stemming/lemmatization).
Multilingüismo: analizadores por campo (ru, uk, en); Análisis de UCI; transliteración; tomar en cuenta la diacrítica.
3. 2 Índice inverso (sparse)
Estructura: lista term → posting (docID, term freq, posiciones).
Clasificación: BM25 (o TF-IDF clásico) con refuerzos de campo.
3. 3 Índice vectorial (dense)
Embeddings de texto (por ejemplo, 384-1024-dimensional).
Estructuras ANN: HNSW, IVF-PQ, Flat (para conjuntos pequeños).
Proximidad coseno/producto interno; calibración con BM25 (híbrido).
3. 4 Facetas y agregados
Prepago/columna de almacenamiento de valores para cuentas rápidas.
Facetas jerárquicas (categoría/subcategoría).
Rangos (precios, fechas).
4) Consultas: filtros + texto completo + clasificación
4. 1 Contratos API (NAT)
Consulta:
GET /v1/search? q = classic slots & limit = 20 & cursor =... & sort = score: desc, created _ at: desc
&filters=brand:("NetEnt","EGT"); price:[10 TO 50];published_at:[2024-01-01 TO ]
&facets=brand,year,price:range(0,10,20,50,100)
Respuesta (fragmento):
json
{
"items": [ { "id":"...", "title":"...", "score": 12. 3, "highlight": { "content": ["..."] } } ],
"facets": { "brand": [{"value":"NetEnt","count":123},...] },
"page": { "limit":20, "has_more":true, "next_cursor":"opaque-token" }
}
4. 2 GraphQL (simplificado)
graphql type Query {
search(query: String!, filter: SearchFilter, first: Int, after: String, sort: [Sort!]): SearchConnection!
}
4. 3 gRPC
proto message SearchRequest {
string query = 1;
map<string,string> filters = 2;
int32 page_size = 3;
string page_token = 4; // курсор repeated string facets = 5;
}
5) Tratamiento del lenguaje natural (NLP)
Tokenización/normalización: Unicode-seguro, contabilidad de guiones/apóstrofes.
Palabras de parada: listas personalizadas por idioma.
Stemming vs lemmatización: para ru/uk mejor lemmatización (calidad> velocidad).
Sinónimos: diccionarios bidireccionales/direccionales; versiones de diccionarios con TTL.
Errores tipográficos (fuzzy): Damerau-Levenshtein con límite de distancia y bustos de coincidencia exacta.
N-grams/edge-ngrams: para autocompletar y consejos.
Transliteración: «shch» ↔ «sh», «kiev/kyiv» - reglas de conformidad.
6) Relevancia y clasificación
6. 1 Puntuación léxica básica
BM25 con la configuración de 'k1', 'b' por colección.
Refuerzos por campos (title ^ 3, tags ^ 1. 5, body^1).
Frescura: 'score + = freshness_boost (decay (created_at))'.
6. 2 Señales de comportamiento
Click-through rate, dwell time, guardar en favoritos (con bayas anti-position).
Deduplicación: pegamento de documentos con contenido ~ idéntico (MinHash/SimHash).
6. 3 Learning-to-Rank (LTR)
Fichi: BM25 por los campos, longitud, frescura, popularidad, coincidencia en la frase, skor posicional.
Modelos: LambdaMART/XGBoost; métricas offline NDCG @ k, MAP, Precision @ k; en línea A/B.
6. 4 Reordenamiento neuro
Dos pasos: recall (BM25/ANN) → top-N (por ejemplo, 200) → cross-encoder rerank.
Contabilidad de costos: tiempo-presupuesto, fallback sin neuro-etapa bajo carga.
6. 5 Búsqueda híbrida (sparse + dense)
Ya sea fusion (normalización de scores y suma) o multi-stage (dense como rerank).
La calibración es importante: min-max/z-score/quantile mapping.
7) Filtración, facetas y acceso
7. 1 Filtros
Operadores: '=', 'IN', rangos, prefijos, caja geo-bounding/geo-distance.
Combinaciones: 'AND' por filtros, 'OR' dentro de múltiples valores (brand IN...).
Seguridad típica: los campos numéricos no se analizan como texto.
7. 2 Facetas
Count-s baratos según las estructuras anticipadas.
Las facetas «aplicadas» muestran las opciones restantes (faceting post-filter).
7. 3 Acceso/multi-tenencia
Los filtros de seguridad se integran antes de la clasificación (pre-filtro).
Campo ABAC/RBAC del documento ('tenant _ id', 'visibility', 'acl').
El token de solicitud está firmado; con multi-tenant - filtro automático 'tenant _ id'.
8) Paginación, cursores y consistencia
Paginación seek-cursor por '(score, tie-breaker)' o por '(created_at, id)' cuando se ordena por tiempo.
Opaco 'page _ token' c HMAC y TTL.
Consistencia: near-real-time (NRT) del índice: latencia 0. 5-2 con entre el registro y la visibilidad. Documente esto en el SLA.
Cross-shard: búsqueda local → k-way merge por orden global, cursores per-shard en token.
9) Autocompletar y pistas
Suggesters: prefix-trie / edge-ngrams по полю `title`.
Queries populares: registro de clics → consejos de popularidad + personalización (segmentos).
Spell-as-you-type: búsqueda fuzzy rápida con límite de distancia '<= 1'.
GET /v1/suggest? q=kaz&limit=8&locale=ru
→ ["casino," "casual games,..."]
10) Highlights y snippets
El índice de posición → extraer frases con coincidencias.
Protección HTML, límite de longitud, combinación de fragmentos adyacentes.
Clasificación de los snippets según la densidad de los términos relevantes.
11) Rendimiento, caché y SLO
Índices: segmentos calientes en memoria; compresión de postings; doc valores para facetas.
Caché: L1 (proceso), L2 (Redis), caché de facetas/agregados; invalidar según la versión del índice.
SLO: P95 <150-200 ms en 'k <= 20', P99 <500 ms; disponibilidad 99. 9%.
Backpressure: reducción de 'k', desconexión de la etapa neuronal en caso de sobrecarga.
Rate limiting por clave API/usuario/tenant.
12) Observabilidad y métricas de calidad
Técnicas:- `search_latency_ms` (P50/P95/P99), `qps`, `timeouts`, `error_rate`
- `cache_hit_ratio`, `facet_cache_hit`, `rerank_share`
- `shard_fanout`, `merge_time_ms`, `ann_recall@k`
- NDCG @ k, MAP, MRR, Recall @ k, Precision @ k en muestreos marcados.
- CTR@k, sCTR (satisfied clicks), dwell time, отказ (pogostick rate).
A/B: fijar «guardrail» métricas (latencia, errores) + objetivo (NDCG proxy).
13) Pruebas
Pruebas de unidad de relevo: comprobar los partidos esperados en las solicitudes clave.
Property-based: resistencia a errores tipográficos/sinónimos/idiomas.
Paginación: sin duplicados en el borde de las páginas (contratos seek).
Seguridad: los filtros de acceso se aplican siempre (incluso en faset-count).
Regresiones de diccionarios: versionar sinónimos y reglas fuzzy.
14) Seguridad y privacidad
Los campos con PII no se indexan como texto; almacenar por separado/cifrar.
Minimizar los textos de origen almacenados (store = false, sólo los campos de snippets).
Query privacy: no lógica solicitudes en bruto con PII; anonimización/hashing.
Multi-tenant: aislamiento estricto de índices o filtro obligatorio 'tenant _ id'.
15) Migración e interoperabilidad
Versionar el diagrama de índice (v1→v2) con entrada doble y conmutación gradual.
Compatibilidad de analizadores: mantenga las cadenas antiguas sin volver a indexar.
La rotación de diccionarios sinónimos/palabras de parada: 'versión', 'activated _ at', rollback.
16) Recetas prácticas
16. 1 Búsqueda léxica clásica (BM25)
Campos: 'título ^ 3', 'tags ^ 2', 'cuerpo ^ 1'.
Analizadores: lenguaje-específico + lemmatización.
Fuzzy para consultas cortas ('<= 3' tokens), 'fuzziness = 1'.
16. 2 Híbrido sparse + dense
1. Búsqueda ANN por embedding de consulta (k = 200)
2. Combinar con top-200 BM25
3. Calibrar y fusionar (Reciprocal Rank Fusion)
4. Tome el top-N (N = 20), opcional - rerank cross-encoder-om con suficiente presupuesto.
16. 3 Navegación facetada del directorio
Prefilter rígido sobre derechos/tenantes
Facetas post-filtro (counts teniendo en cuenta los filtros activos)
Clasificación: por relevancia o por campo de negocio (precio/novedad)
17) Consultas de ejemplo (pseudo-DSL)
Filtros y clasificación:json
{
"query": "live casino,"
"filters": {
"country": ["EE","LV","LT"],
"license": ["MGA","UKGC"],
"launched_at": {"gte": "2023-01-01"}
},
"sort": ["_score:desc","launched_at:desc"],
"facets": ["country","license"],
"page": {"limit": 20, "cursor": "opaque"}
}
Geopeisk:
json
{
"query": "casino",
"geo": {"lat": 59. 437, "lon": 24. 753, "radius_km": 50}
}
Autocompletar:
json
{ "prefix": "evo", "field": "brand_suggest", "limit": 8 }
18) Patrones UX
Chips de filtros activos + «restablecer todo».
Resultados vacíos: mostrar «pruébalo...» (sinónimos, quitar el filtro).
«Pistas a cero»: consultas/categorías populares.
Paginación con el cursor (botón «Más») y el scroll infinito; indicador fijo de filtros aplicados.
Interruptores individuales «tener en cuenta errores tipográficos», «coincidencia exacta de la frase».
19) Errores frecuentes y anti-patrones
No hay tie-breaker al ordenar → tomas/carreras de caballos.
Las facetas sin tener en cuenta los filtros activos → counts «falsos».
Aplicación de filtros de acceso después de la clasificación.
Mezclar diferentes idiomas con un solo analizador.
Paginación profunda OFFSET/LIMIT en lugar de seek-cursor.
Fuzzy ilimitado → explosión por latencia.
20) Checklist de implementación
1. Identifique los campos y sus tipos, asigne analizadores per-locale.
2. Diseñar el índice inverso + (opz.) ANN vectorial.
3. Implemente un parser de consultas y filtros de acceso seguros (pre-filtro).
4. Configurar BM25 y refuerzos de campo; conecte las facetas.
5. Introduzca los cursores (opaque, HMAC, TTL) y k-way merge por chardos.
6. Agregue autocompletar, highlites, blindaje seguro.
7. Métricas: latencia, NDCG @ k, CTR; caché L1/L2.
8. Marco A/B para la afinación de relevancia.
9. Documenta SLA: latencia NRT, límites 'limit', garantía de consistencia.
10. Plan de migración: versiones del índice, diccionarios y analizadores.
Una capa bien diseñada de filtrado y búsqueda de texto completo no solo es un índice rápido, sino también un contrato de protocolo claro con cursores, seguridad, UX predecible y relevancia medible. Este enfoque escala entre miles y miles de millones de documentos y soporta tanto búsquedas léxicas clásicas como escenarios híbridos modernos con rangos neuronales.