Tecnología e Infraestructura → Elasticsearch y búsqueda de texto completo
Elasticsearch y búsqueda de texto completo
1) El papel de Elasticsearch
Elasticsearch (ES) es un sistema de búsqueda y análisis distribuido basado en índices invertidos y estructuras de columnas para agregaciones. Ella dice:- Texto completo: relevancia (BM25), morfología, fuzzy/tipo tolerante.
- Facetas y agregaciones: cortes rápidos por atributos.
- Búsqueda híbrida: BM25 + kNN vectoriales (semántica).
- Velocidad de desarrollo: Query DSL, ingest pipelines, un ecosistema rico.
Para iGaming/fintech: búsqueda de juegos/proveedores, promociones y reglas, facetas de respuesta rápida (proveedor, volatilidad, RTP, lenguaje), búsqueda de KYC/AML registros, análisis de registros y alertas.
2) Modelo de datos y mappings
2. 1 Índices y tipos de campo
'text' (campo analizado) - para texto completo.
'keyword' - valores exactos/agregaciones/ordenamiento.
`date`, `long/double`, `boolean`, `ip`, `geo_point`.
'nested' - matrices de objetos con correlación de campo correcta.
'dense _ vector': representaciones vectoriales (embeddings).
2. 2 Estrategia de campo múltiple
Almacene el campo en varias vistas: 'name. text '(analizado),' name. raw` (keyword), `name. ngram '(para autocompletar).
json
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ru_morph",
"fields": {
"raw": { "type": "keyword", "ignore_above": 256 },
"ngram": { "type": "text", "analyzer": "edge_ngram_2_20" }
}
},
"provider": { "type": "keyword" },
"tags": { "type": "keyword" },
"rtp": { "type": "float" },
"released_at": { "type": "date" },
"lang": { "type": "keyword" },
"embedding": { "type": "dense_vector", "dims": 384, "index": true, "similarity": "cosine" }
}
},
"settings": {
"analysis": {
"filter": {
"ru_stop": { "type": "stop", "stopwords": "_russian_" },
"ru_stemmer": { "type": "stemmer", "language": "russian" },
"syn_ru": { "type": "synonym", "lenient": true, "synonyms": [
"слот,игровой автомат => слот",
"джекпот,суперприз => джекпот"
] }
},
"analyzer": {
"ru_morph": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "ru_stop", "ru_stemmer", "syn_ru"]
},
"edge_ngram_2_20": {
"type": "custom",
"tokenizer": "edge_ngram",
"filter": ["lowercase"],
"char_filter": [],
"tokenizer": "edge_ngram"
}
},
"tokenizer": {
"edge_ngram": { "type": "edge_ngram", "min_gram": 2, "max_gram": 20 }
}
}
}
}
2. 3 Nested para facetas
Los atributos de la vista 'features: [{name, value}]' diseñan 'nested', de lo contrario las facetas darán falsas coincidencias.
3) Relevancia: BM25, busto e híbrido
3. 1 Clásico (BM25)
Combine los campos con escalas (title ^ 4, tags ^ 2, description).
Utilice 'minimum _ should _ match' para controlar las coincidencias «ruidosas».
3. 2 Vectores (kNN) + BM25 (rerank)
Embeddings (por ejemplo, 384-768) en 'dense _ vector'.
Primero kNN por vector (top 200-500), luego rescore BM25 + business boosts (novedad, RTP, licencia de región).
json
{
"knn": {
"field": "embedding",
"query_vector": [/... /],
"k": 400, "num_candidates": 2000
},
"query": {
"bool": {
"should": [
{ "multi_match": {
"query": "египетские слоты джекпот",
"fields": ["title^4","tags^2","description"],
"type": "best_fields",
"minimum_should_match": "60%"
}}
],
"filter": [
{ "term": { "region": "TR" }},
{ "range": { "rtp": { "gte": 94.0 }}}
]
}
},
"rescore": {
"window_size": 400,
"query": {
"rescore_query": {
"function_score": {
"query": { "match_all": {} },
"boost_mode": "sum",
"functions": [
{ "gauss": { "released_at": { "scale": "180d", "offset": "30d", "decay": 0.5 } } },
{ "field_value_factor": { "field": "popularity", "factor": 0.2, "modifier": "log1p" } }
]
}
}
}
},
"highlight": { "fields": { "title": {}, "description": {} } }
}
4) Autocompletar y pistas
Enfoques:- Edge N-gram en el sub-campo 'title. namb '(rápido, simple).
- Completion suggesters ('completion' campo) son pistas rápidas, pero una ruta de indexación separada.
- Search-as-you-type: combina la tokenización para iniciar la palabra y las palabras.
json
{ "suggest": { "game-suggest": { "prefix": "book o", "completion": { "field": "title_suggest", "fuzzy": { "fuzziness": 1 }}}}}
5) Sinónimos, errores tipográficos y multilingüismo
Sinónimos: descargue el archivo/lista a través del filtro 'synonym'; separe los dominios (casino/deportes).
Errores tipográficos: 'fuzziness: AUTO' en 'multi _ match', limite la longitud y los campos. Para consejos, el modo 'fuzzy' es completion.
- Índice-per-local (es/en/tr/pt-BR) o esquema multianálisis: 'title _ es', 'title _ en'.
- Разные analyzers: `russian`, `english`, `turkish`, `portuguese`.
- Transfiera el idioma a la clave de enrutamiento (enrutamiento) para mantener las localizaciones «calientes» más cerca del usuario.
6) Filtros, facetas y agregaciones
Para las facetas, utilice las agregaciones 'keyword' y 'nested'.
Evite los campos cardinales (IDs únicos) en las agregaciones - saque en 'runtime fields' o vitrinas preliminares.
json
{
"size": 20,
"aggs": {
"by_provider": { "terms": { "field": "provider", "size": 20 } },
"by_volatility": { "terms": { "field": "volatility" } },
"rtp_hist": { "histogram": { "field": "rtp", "interval": 1 } }
}
}
7) Entrada de datos y borrado de texto
Ingest pipelines: normalización, extracción de campos, geo-encoding, eliminación de HTML.
Attachment/ingest-ocr (según sea necesario): indexación de PDF/imágenes (atento a PII).
Lemmatización: a través de analizadores o pipelines externos (tokens de precomputo).
8) Chardas, réplicas e ILM
8. 1 Tamaños y charding
Menos chardos, mejor. Objetivo: 10-50 GB por shard para cargas mixtas.
Comience con 'number _ of _ shards: 1-3', escale por el hecho. Réplicas: mínimo de 1 en venta.
8. 2 ILM (Lifecycle)
hot → warm → cold → delete para logs/historial promocional.
Compresión (force merge) para segmentos «fríos».
Para catálogos y búsquedas de productos - hot «indefinido» con optimización periódica.
8. 3 Algoritmo de migración sin downtime
El nuevo índice 'games _ v2' → alias 'games' cambia después de 'reindex' y backfill. Campos Deprecated - quitar gradualmente.
9) Snapshots, DR y actualizaciones
Snapshots al almacén de objetos (S3/GCS), programación y validación de recuperación.
Actualizaciones de nodo de rolling, validación de awareness de allocation shard (por zona).
Planes de DR: replicación de región cruzada (CCR) para índices críticos (directorios, directorios).
10) Seguridad y PII
TLS/mTLS entre el cliente y el clúster.
RBAC: roles por índice/operación; Dev/Stage/Prod - separado.
PII/PCI: no indexe campos con datos personales sin necesidad; utilice el enmascaramiento ingest.
Right to be forgotten: almacena enlaces a documentos para borrarlos por user_id; soft-delete + reindex/anunciation.
11) Observabilidad y búsqueda de SLO
Métricas:- P50/P95/P99 latency en query, errores 4xx/5xx.
- Cache hit (query cache / shard request cache).
- Heap usage, GC паузы, segment merges, threadpools (search/write).
- Hot shards/hot nodes, rejections.
- KNN: `graph_hits`, `search_k`, latency, recall@k.
- Búsqueda de juegos: P95 ≤ 200 ms, errores <0. 5% en una ventana de 30 minutos.
- Pistas: P95 ≤ 80 ms.
- KNN híbrido: P95 ≤ 350 ms para los resultados top-20.
12) FinOps: costo y rendimiento
Tamaño del índice: ahorre en tokenización, desactive los 'fielddata' innecesarios, use 'doc _ values' sólo donde sea necesario.
Segmentos: planifique una política merge, no permita «trituración».
KNN es más caro por RAM/CPU: limite dims, 'num _ candidates', pre-filter por BM25.
Campos calientes en RAM: monitoree el campo data/heap; lleve las agregaciones «pesadas» a índices separados.
13) Ejemplos de consultas
13. 1 Multi-campo de texto completo con refuerzo
json
{
"query": {
"multi_match": {
"query": "book of",
"fields": ["title^4","title.ngram^2","tags^2","description"]
}
},
"sort": ["_score", { "released_at": "desc" }]
}
13. 2 Filtros + facetas
json
{
"query": {
"bool": {
"must": [{ "match": { "title": "египет" }}],
"filter": [
{ "terms": { "provider": ["Novomatic","PragmaticPlay"]}},
{ "range": { "rtp": { "gte": 95 }}}
]
}
},
"aggs": {
"by_provider": { "terms": { "field": "provider" } },
"by_year": { "date_histogram": { "field": "released_at", "calendar_interval": "year" } }
}
}
13. 3 Filtrado de atributos
json
{
"query": {
"nested": {
"path": "features",
"query": { "bool": {
"must": [
{ "term": { "features.name": "volatility" }},
{ "term": { "features.value": "high" }}
]
}}
}
}
}
13. 4 Búsqueda de inicio de sesión (ECS) con highlight
json
{
"query": {
"bool": {
"must": [{ "match_phrase": { "message": "payment declined" }}],
"filter": [
{ "term": { "service.name": "payments" }},
{ "range": { "@timestamp": { "gte": "now-1h" }}}
]
}
},
"highlight": { "fields": { "message": { "number_of_fragments": 0 } } }
}
14) Multi-tenant y aislamiento
Índice por tenante (mejor) o campo 'tenant _ id' + filtro ACL (más caro en agregaciones).
Enrutando por 'tenant _ id' para localizar los chardos.
Limite las solicitudes de tenant a límites/tiempos de espera, 'query. phase` guard-rails.
15) Lista de verificación de implementación
1. Esquema: 'text/keyword/nested' + multipolos, 'dense _ vector' si es necesario.
2. Analizadores per-language, sinónimos, edge-namb para autocompletar.
3. Relevancia: BM25 busts + híbrido kNN→rescore.
4. Facetas: keyword/nested, agregaciones sólo por campos «saludables».
5. Indexación: ingest pipelines (normalización), arranque en batch.
6. Charding: comience con pequeñas, alias para mudanzas, ILM para registros «largos».
7. DR: programación de snapshots, validación de recuperación, CCR para índices críticos.
8. Seguridad: TLS, RBAC, enmascaramiento PII, política de eliminación.
9. Observabilidad: latency, heap/GC, cache hit, hot shards, rejections.
10. FinOps: tamaño del índice, parametrización kNN, desactivación del extra 'doc _ values/fielddata'.
16) Anti-patrones
Un índice «para todo»: diferentes dominios (directorio, registros, transacciones) requieren diferentes configuraciones.
Irreflexivo 'fuzziness: AUTO' en todos los campos → lento y ruidoso.
Los sinónimos «se comen el significado»: no compartir los dominios de los diccionarios.
Sin embargo, donde se necesitan paquetes de campos → facetas falsas.
Demasiados chardos (uno por documento) son gastos generales del cluster state.
No utilizar alias en las migraciones: tiempo de inactividad y enlaces «rotos».
Indexación PII «tal cual» - riesgos regulatorios y reindexaciones costosas.
17) Contexto iGaming/Fintech: recetas rápidas
Búsqueda de juegos: 'multi _ match' con el refuerzo 'title ^ 4', 'tags ^ 2', facetas por proveedor/volatilidad, filtros por región/moneda, híbrido con vectores para 'tema' (por ejemplo, 'egipto', 'fruit classic').
Promociones/bonificaciones: sinónimos («freespines», «tiradas gratis»), filtros de fecha 'active _ from/active _ to', pistas a través de completion.
Revistas KYC/AML: esquema ECS, texto completo por 'message', agregaciones por 'rule _ name', 'country', anomalías por '@ timestamp' histograma.
Referencia de proveedores: campos clave para facetas y ordenaciones; las descripciones de texto son 'text' con morfología.
Páginas reguladoras: campos multilingües, 'search _ as _ you _ type' para sugerencias suaves.
Resultado
Una búsqueda efectiva en Elasticsearch no es solo «encender BM25»: son los analizadores y mappings adecuados, multipolos y nested, vectores híbridos VM25 +, facetas y agregaciones ordenadas, disciplina de charding e ILM, SLO y observabilidad nítidos, y seguridad y FinOps. Con estos principios, su búsqueda será rápida, relevante y predecible, y resistirá los picos de tráfico de la plataforma de productos.