Your client can’t tell the difference.
Not a new SDK, not a « mostly compatible » dialect: the official Elasticsearch libraries connect to it, the handshake they perform on connect succeeds, and the requests you already send come back in the shape they already parse.
The inverted index itself isn’t reinvented — that’s Tantivy, the Rust equivalent of Lucene. The work is the compatibility layer on top of it, and it’s checked rather than claimed: Elastic’s own REST test suite is replayed against a running build, case by case, and what that run found is the number below — not a target, not a claim.
from elasticsearch import Elasticsearch # the official client, unmodified
es = Elasticsearch("http://localhost:9200")
es.indices.create(index="books", mappings={"properties": {
"title": {"type": "text"}, "author": {"type": "keyword"},
"year": {"type": "integer"}}})
es.index(index="books", id="1", refresh=True,
document={"title": "Bel-Ami", "author": "Maupassant", "year": 1885})
es.search(index="books", query={"match": {"title": "bel ami"}})
# {'took': 3, 'hits': {'total': {'value': 1, 'relation': 'eq'}, ...measured conformance
measured 1 September 2026 · 35 days ago
older than a month
That measurement is 35 days old — past the 30 days after which this page stops presenting it as the current state. Read it as a snapshot taken on 1 September 2026, and check the report for where it stands now.
82.7%
172 / 208 cases — fidelity inside the declared scope
Of the cases that land on something this page claims, the share that answers exactly like Elasticsearch: 172 of 208. Cases that fail on a capability the repo declares refused are out of that denominator — they are the price of the scope, and the list below names every one of them.
14.7%
172 / 1173 cases — of Elasticsearch's own suite
The same 172 cases against the whole suite Elastic ships: 1173. This is how much of Elasticsearch is covered at all — a fraction, and the number that keeps the first one honest.
- what ran
- Elastic’s own REST suite, version 7.10.2 (Apache-2.0), replayed unmodified against a running build — 1173 cases across 107 suites. Not tests written here to pass here.
- against
ferrite-0.10.0, announcing API version 8.15.0, measured on 1 September 2026.- declared
- 215 capabilities in
compat.yaml: 103 supported, 68 partial, 44 refused — the two lists on this page are generated from it. - raw report
- docs/conformance.json — every case, its verdict and its reason. docs/compat.md is the same thing for the capabilities.
in scope
Generated from the repository’s compat.yaml, one line per table: 103 capabilities supported and 68 partial — the partial ones marked, because a capability whose edges are missing isn’t a capability you can plan on. Each is named as the repository names it, in French where the repository is French: a translation on this page is one more thing to keep true, and this page has just stopped keeping such things by hand.
- cluster
GET /·HEAD /(ping) ·GET /_cluster/health,/_cluster/health/{index}partial ·GET /_cat/indices,/_cat/indices/{index}partial ·GET /_cat/healthpartial ·GET /_nodes,/_nodes/{spec}partial ·Content-Encoding: gzip/deflatesur le corps d'une requête- indices
- Création à l'écriture · Expressions d'index (
a,b,logs-*,_all, exclusions, alias) ·PUT /{index}partial ·DELETE /{index}·HEAD /{index}·GET /{index}·GET /{index}/_mapping·GET /{index}/_settingspartial ·PUT /{index}/_settingspartial ·PUT /{index}/_mappingpartial ·POST /{index}/_refresh·POST|GET /_analyze,/{index}/_analyzepartial · Mapping dynamique · Alias · Templates d'index —_index_templateet_templatepartial ·GET /{index}/_statspartial - analyzers
standard(défaut) ·simple·whitespace·keyword·stop·english·french·snowball·danish,dutch,german,hungarian,italian,norwegian,portuguese,romanian,russian,spanish,swedish,turkish· Analyzers sur mesure (settings.analysis)- custom analysis
analysis.analyzerde typecustom· Tokenizerspartial ·ngrametedge_ngram— tokenizer et filtre · Filtrespartial- field types
text·keyword·byte,short,integer,long·float,doublepartial ·boolean·datepartial · Tableaux de valeurs ·null·object(sous-objet), déclaré ou deviné ·nestedpartial ·join(parent/enfant)partial ·analyzerpartial ·search_analyzer·copy_to·storepartial · Multi-fields (fields) ·ignore_above·index- ingestion
PUT|POST /{index}/_doc/{id}partial ·POST /{index}/_doc·PUT|POST /{index}/_create/{id}·GET /{index}/_doc/{id}·HEAD /{index}/_doc/{id}·DELETE /{index}/_doc/{id}·POST|PUT /_bulk,/{index}/_bulkpartial ·refresh(true/false/wait_for) ·POST /{index}/_update/{id}partial ·GET|POST /_mget,/{index}/_mget·GET|POST /{index}/_count· Versionnage optimisteif_seq_no/if_primary_term·POST /{index}/_delete_by_querypartial ·POST /{index}/_update_by_querypartial- scroll
?scroll=1msur_search·POST|GET /_search/scroll·POST|GET /_search/scroll/{scroll_id}·DELETE /_search/scroll,/_search/scroll/{scroll_id}- index patterns
catalogue·produits,marques·audits-2026.08.*·_all,*, URL sans index ·audits-*,-audits-2026.07.*·ignore_unavailable·allow_no_indices·expand_wildcardspartial- aliases
POST /_aliasespartial ·PUT|POST /{index}/_alias/{nom}et ses six autres URL (/_alias/{nom},/{index}/_alias,/_alias,_aliasespour chacune) ·DELETE /{index}/_alias/{nom}·GET /_alias,/_alias/{nom},/{index}/_alias,/{index}/_alias/{nom}·HEAD /_alias/{nom},/{index}/_alias/{nom}·aliasesdansPUT /{index}·is_write_index- cluster settings
GET|PUT /_cluster/settingspartial ·action.destructive_requires_name- query DSL
match_all·match_none·matchpartial ·multi_matchpartial ·match_phrasepartial ·match_phrase_prefixpartial ·existspartial ·term·ids·prefixpartial ·wildcardpartial ·regexppartial ·fuzzypartial · les champs de métadonnées en clause (_id,_index, …)partial ·constant_score·dis_max·function_scorepartial ·boosting·termspartial ·rangepartial ·boolpartial ·_name(nommer une clause),matched_queries,include_named_queries_score·query_stringpartial ·simple_query_stringpartial- full-text search
lenient·type: best_fields(défaut) ·type: most_fields·type: phrase·type: phrase_prefix·operatorsousphrase/phrase_prefixpartial- search body
POST|GET /{index}/_search,POST|GET /_search·query·from/size·sortpartial ·_source·fieldspartial ·docvalue_fieldspartial ·stored_fields·highlightpartial ·track_total_hitspartial · Scoringpartial · Format de réponse ·preferencepartial ·aggs/aggregationspartial ·scroll·min_score·search_after·POST /{index}/_pit,DELETE /_pit, et le blocpitdu corps ·timeout(paramètre et corps)partial ·ignore_unavailable,allow_no_indices,expand_wildcards·GET|POST /{index}/_explain/{id},explain: truepartial ·GET|POST /{index}/_field_capspartial ·GET|POST /{index}/_validate/querypartial- date math
now·now±<n><unité>·now/<unité>·<ancre>||<opérations>· date partielle (2026-03-15,2026-03,2026-03-15T12) ·formatsurrange· dansterm,terms,match, et sous unnested·time_zone- aggregations
min,max,sum,avg,value_count,stats·termspartial ·rangepartial ·histogrampartial ·date_histogrampartial · Sous-agrégations ·extended_statspartial ·percentilespartial ·top_hitspartial ·filterpartial- nested
{"nested": {"path", "query"}}· Clauses internespartial ·score_modepartial · Champs devinés sous unnested- join
{"type": "join", "relations": {...}}· Indexation ·has_child,has_parentpartial ·parent_id·{"term": {"lien": "article"}}·routingpartial
A container you forget is running.
The final image is a scratch holding one statically linked binary — 1 layer against 10. Nothing else — no libc, no shell, no JVM, nothing to patch on a Tuesday.
measured cost
measured 2 September 2026 · 34 days ago
older than a month
That measurement is 34 days old — past the 30 days after which this page stops presenting it as the current state. The binary grows: between the repository’s last two campaigns the image moved and so did the startup, which is exactly why this table is read rather than typed. Check the measurement for where it stands now. The repository flags this campaign as run on a modified tree, so the image measured may not be the one c2b4743 builds — Vrai si un des fichiers dont l'image est faite (src/, Cargo.toml, Cargo.lock, Dockerfile) differait de mesure.ferrite_sha pendant la campagne — donc si l'image mesuree pourrait ne pas etre celle que ce commit produit. Un README modifie au meme moment ne compte pas : il ne change pas un octet du binaire.
| Elasticsearch 8.15.0 | Spunto Search 0.11.0 | |
|---|---|---|
| image, as a registry serves it | 669.1 MB | 4.3 MB |
La somme des blobs qu'un registre sert pour cette image — le manifeste, la configuration et les couches telles qu'elles sont poussees. C'est ce qu'un | ||
| image, unpacked | 1.27 GB | 10.2 MB |
La somme des couches une fois depliees, c'est-a-dire ce que le systeme de fichiers de l'image occupe une fois l'image tiree. | ||
| memory at rest | 1.08 GB | 4.9 MB |
La somme des VmRSS de tous les processus du cgroup du conteneur, en kilo-octets, relevee 2 s apres le premier | ||
| docker run → first response | 18.1 s | 172 ms |
Le temps entre | ||
| what the container runs | /bin/tini | /ferrite — 10.2 MB |
La taille du fichier que l'ENTRYPOINT du conteneur execute. | ||
Both columns are measured by tests/compat/measure_container.sh on the same machine, in the same conditions, against a real Elasticsearch 8.15.0 pulled as Elastic publishes it — never against an idea of what Elasticsearch costs. The 172 ms is the whole docker run round trip to a first served request, and it is the median of 5 consecutive starts: 263 ms · 170 ms · 174 ms · 169 ms · 172 ms. For this binary most of that is Docker creating the container.
- what was measured
ferrite:0.11.0, built here from the repository’s Dockerfile atc2b4743, againstdocker.elastic.co/elasticsearch/elasticsearch:8.15.0.- how
./tests/compat/measure_container.sh --json docs/container.jsonon linux/amd64, Docker 29.7.2 (overlayfs). La version du serveur Docker et son magasin d'images ne changent pas ce que cet outil mesure — il compte les octets de l'archive — mais ils changent ce que les AUTRES outils repondent a la meme question :docker image inspect --format '{{.Size}}'rendait la taille decompressee jusqu'a Docker 28 et rend la compressee depuis la 29, et la colonne DISK USAGE dedocker imagesen additionne encore une troisieme.- docker run
-p 9299:9200for Spunto Search,-p 9299:9200 -e discovery.type=single-node -e xpack.security.enabled=false -e ES_JAVA_OPTS=-Xms512m -Xmx512mfor Elasticsearch — part of the definition of the memory and startup rows, not a detail.- raw measurement
- docs/container.json — every figure above, its definition and the manifest digest of the exact bytes counted.
what that changes
Not the query — the deployment. A search engine that boots instantly and fits in a few megabytes stops being a piece of infrastructure with its own capacity plan and becomes a detail: a sidecar next to the app, a service in a CI job that isn’t worth caching, a container in a dev environment that’s already up before you’ve switched windows.
It is a single node holding a single shard on a single volume. That is the whole trade: no replication, no failover, no rebalancing — and none of the machinery that makes those cost what they cost.
services:
search:
build: https://github.com/spuntodotnet/search.git
ports:
- "9200:9200"
volumes:
- search-data:/data
volumes:
search-data:No image is published yet, so this builds from the repo — the same scratch image the table measures. Prefer no Docker at all? The releases carry a static musl binary for x86-64 and arm64.
Nothing fails quietly.
The failure mode that matters in a compatibility layer isn’t a missing feature, it’s a missing feature that answers 0 hits. Every clause, field type and route that isn’t implemented returns an error in Elasticsearch’s own format, with a type — not_implemented_in_ferrite_exception — that means precisely « ES can do this, we can’t yet ».
Some refusals are permanent and deliberate, and they’re the interesting ones: cardinality and slop are refused because Tantivy and Lucene disagree on what they should return, and both would have been easy to accept and quietly wrong. The reason for each refusal is in the repository, and it’s reproduced below rather than summarised.
out of scope
The 44 refusals declared in compat.yaml, by family — deliberate first, « not written yet » last.
- out of scope, on purpose
- Cluster distribué —
_cluster/state,_cluster/stats,_cluster/reroute,_cluster/allocation/explain,_cluster/pending_tasks,_remote/info,_nodes/stats,_tasks· Snapshots, dépôts, restauration —_snapshot/*· Flux de données —_data_stream,data_streamdans un template · Tout ce qu'Elastic ajoute autour du moteur — sécurité et rôles (_security), machine learning (_ml), cycle de vie (_ilm,_slm),_watcher,_transform,_enrich,_eql,_sql,_esql,_inference, connecteurs, *search applications*,_rollup,_ccr,_graph, licence,_monitoring· Scripting —_scripts,_search/template,_render/template, Painless ·script_fields,runtime_mappings·routing,filter_path,typed_keys·search_type,max_concurrent_shard_requests,pre_filter_shard_size,batched_reduce_size - engine divergence
finnish· Noms de champ pointés (a.b) ou réservés ·type: cross_fields,bool_prefix·slop·histogram,date_histogram,rangesur un champ multivalué ·cardinality· Champtextdans une clause interne · Tri et agrégations sur un sous-champ denested, depuis la racine- refused by Elasticsearch too
- L'API typée — un
{type}dans l'URL, un_typedans la réponse,include_type_name·fromavecscroll· Contexte expiré, fermé, ou jamais ouvert ·DELETE /{alias}· à l'indexation - not written yet
- Les
_cat/*autres que_cat/indiceset_cat/health· Cycle de vie d'un index —_close,_open,_forcemerge,_shrink,_split,_clone,_rollover,_recovery,_segments,_flush,_upgrade,_cache/clear,_shard_stores,_resolve/index· Les autres routes de recherche —_search_shards,_termvectors,_mtermvectors,_suggest,_source·GET /{index}/_mapping/field/{champs}·_component_template,_simulate_index_template,_simulate·arabic,czech,greek,thaiet les autres langues ·char_filter· Un analyzer de type autre quecustom(french,standardparamétré…) · Tout autre type (geo_point,ip,binary…) · Autres paramètres de champ (null_value,doc_values,norms…) ·version/version_typeexternes ·_reindex, pipelines d'ingestion ·filter,routing,index_routing,search_routingsur un alias ·GET /_cat/aliases·remove_indexetaddd'un alias du même nom dans le mêmePOST /_aliases·GET /{index}/_aliassur un index fermé ·intervals,terms_set,script,span_*… ·collapse,knn,seq_no_primary_term,post_filter,suggest,rescore,track_scores,q,terminate_after,version,indices_boost,profile,slice,stats,ext,retriever·rest_total_hits_as_int·_msearch,_search/template·composite,filters,nested,significant_terms,date_range,ip_range,percentile_ranks,median_absolute_deviation… ·nesteddans unnested·inner_hits,ignore_unmapped
why each refusal — 44 entries, in the repository’s words
Quoted verbatim from compat.yaml, in the language the repository is written in: a translation here would be one more thing to keep true, and this page has just stopped keeping such things by hand.
out of scope, on purpose
- Cluster distribué —
_cluster/state,_cluster/stats,_cluster/reroute,_cluster/allocation/explain,_cluster/pending_tasks,_remote/info,_nodes/stats,_tasks - ferrite est mono-nœud et mono-shard : il n'y a ni allocation, ni réallocation, ni tâche distribuée à rapporter, et une réponse plausible inventée pour ces routes serait un mensonge sur la nature du serveur.
- Snapshots, dépôts, restauration —
_snapshot/* - la sauvegarde d'un ferrite est la copie de son répertoire de données, ou l'export par
scroll; un dépôt de snapshots répliqué est de la mécanique de cluster. - Flux de données —
_data_stream,data_streamdans un template - un flux de données est une suite d'index gérée par
_rolloveret l'ILM, donc de l'exploitation de cluster posée au-dessus du moteur. Le refus est déclaré ici parce qu'il est exercé :helpers.reindexdu client officiel demandeGET /_data_stream/{cible}avant de copier, sur toute cible — c'est la suite serveur du client Python qui l'a montré, et sans cette ligne l'appel comptaitindeterminé, donc contre nous. - Tout ce qu'Elastic ajoute autour du moteur — sécurité et rôles (
_security), machine learning (_ml), cycle de vie (_ilm,_slm),_watcher,_transform,_enrich,_eql,_sql,_esql,_inference, connecteurs, *search applications*,_rollup,_ccr,_graph, licence,_monitoring - ce sont des produits posés sur le moteur, pas le moteur : chacun a son propre modèle de données et sa propre API, et aucun n'est ce qu'un client Elasticsearch existant appelle pour chercher des documents. C'est le corpus d'usage qui a montré qu'aucune capacité ne les réclamait — donc que 19 % de ses requêtes tombaient dans un trou de la déclaration, ni servies ni refusées.
- Scripting —
_scripts,_search/template,_render/template, Painless - un moteur de script est un langage à embarquer, à isoler et à maintenir : c'est exactement le genre de poids que ferrite existe pour ne pas porter.
script_fields,runtime_mappings- les deux définissent des champs calculés par un script Painless, que ferrite n'exécute pas. La mesure le confirme plutôt que la supposition : sur les 444 requêtes du corpus qui portent
runtime_mappings, 425 l'envoient vide (des gabarits de tracks Rally), et sur les 19 non vides 18 portent un script. L'objet vide est donc accepté — il ne définit aucun champ, donc ne demande rien, et ES rend la même réponse avec ou sans (mesuré) ; un objet non vide est refusé explicitement. routing,filter_path,typed_keys- ferrite est mono-shard,
routingn'a rien à choisir ; les deux autres changent la forme de la réponse, et une forme qui dépend d'un paramètre est une seconde API à mesurer. search_type,max_concurrent_shard_requests,pre_filter_shard_size,batched_reduce_size- ils reglent la façon dont une recherche se distribue entre shards ; il n'y en a qu'un, donc rien à distribuer et rien à régler.
engine divergence
finnish- le stemmer finnois de
rust-stemmerss'écarte de celui de Lucene sur 13 mots des 84 399 du vocabulaire finnois de Snowball (0,015 %) : il coupe la voyelle finale d'un emprunt à diacritique étranger là où l'algorithme la garde (garcíarendgarcíchez lui etgarcíachez ES ; de mêmebundesstraße,españa,musée). Un analyzer n'est jamais livré sous le nom d'ES tant qu'il n'est pas mesuré identique — un écart de 0,015 % rendu en 200 est le pire résultat possible ici. - Noms de champ pointés (
a.b) ou réservés - un point est le séparateur de chemin d'un objet : le porter dans un nom rendrait ambigu ce qu'un
client.villedésigne. Le préfixe_, lui, n'est pas réservé — seuls le sont les champs de métadonnées d'ES (_id,_source,_seq_no…) et les racines des colonnes internes de ferrite (_elem,_nelem,_join_parent), qu'un champ utilisateur écraserait. type: cross_fields,bool_prefix- le premier demande des statistiques de termes fusionnées entre champs, le second un scoring de suggestion : les approcher rendrait un autre classement que celui qu'un client attend.
slop- refusé quel que soit le type, pour la raison qui le fait refuser dans
match_phrase(divergence n° 2). histogram,date_histogram,rangesur un champ multivalué- l'agrégation de tantivy compte les valeurs, Elasticsearch compte les documents : un document dont le champ vaut
[1, 2, 3]tombe trois fois dans le bucket qui les contient (mesuré :doc_countde 4 là où ES en compte 2). Le refus n'est prononcé que si la colonne est réellement multivaluée — un champ à une valeur par document, le cas courant, reste servi et exact.terms,value_countetstatsne sont pas concernés : leurs comptes coïncident avec ceux d'ES. cardinality- l'estimation de tantivy diffère de celle d'ES (mesuré : 582 valeurs distinctes annoncées là où ES en compte 598), y compris sous le seuil où ES est exact — un compte approché sous le nom d'ES serait faux sans le dire.
- Champ
textdans une clause interne - les colonnes portent la valeur, pas les termes analysés : interroger son multi-field
.keyword, ou sortir la clause dunested. - Tri et agrégations sur un sous-champ de
nested, depuis la racine - ils porteraient sur les valeurs à plat, donc sur autre chose que ce que la requête a filtré. Chez Elasticsearch ces valeurs vivent dans des documents cachés : une agrégation n'en voit aucune et rend son résultat vide (
null,0.0,buckets: []), un tri est refusé (it is mandatory to set the [nested] context on the nested sort field). ferrite les porte sur le document parent : il rendait donc une moyenne de7.0là où ES rendnull, et un ordre en 200 là où ES rend 400. Un chiffre plausible et faux est le pire des résultats — le refus est explicite, et c'est le même que pour la requête équivalente (divergence n° 10).
refused by Elasticsearch too
- L'API typée — un
{type}dans l'URL, un_typedans la réponse,include_type_name - elle a disparu en 8.x, la version que ferrite annonce : un vrai Elasticsearch 8 échoue au même endroit, et la rendre reviendrait à annoncer une version qu'on ne sert pas.
fromavecscroll- comme ES :
action_request_validation_exception. - Contexte expiré, fermé, ou jamais ouvert
- 404
search_phase_execution_exception, causesearch_context_missing_exception— la forme exacte d'ES, celle que les clients reconnaissent. DELETE /{alias}- effacer des index que le client n'a pas nommés n'est pas une suppression, c'est un accident ; ES 8 refuse de la même façon (« The provided expression [x] matches an alias, specify the corresponding concrete indices instead »).
- à l'indexation
{"d": "now"}est refusé, comme chez ES : le document porterait une date qui dépend de l'instant où il a été écrit.
not written yet
- Les
_cat/*autres que_cat/indiceset_cat/health - ce sont des vues de texte sur un état que ferrite a pour la plupart ; elles ne sont pas écrites, et leurs tests exigent en plus les colonnes
h,sethelpque les deux_catexistants n'ont pas non plus. - Cycle de vie d'un index —
_close,_open,_forcemerge,_shrink,_split,_clone,_rollover,_recovery,_segments,_flush,_upgrade,_cache/clear,_shard_stores,_resolve/index - la moitié de ces routes n'a pas de sens sans shards (
_shrink,_split,_recovery,_shard_stores) ; l'autre moitié suppose un index qu'on peut arrêter de servir sans le supprimer (_close/_open), état que ferrite n'a pas. - Les autres routes de recherche —
_search_shards,_termvectors,_mtermvectors,_suggest,_source - aucune n'est demandée par le code client qu'on cherche à servir.
GET /{index}/_mapping/field/{champs}- route absente (
no handler found) : ferrite a pourtant le mapping, c'est un manque et pas une impossibilité — 15 cas de la suite d'Elastic tombent dessus. _component_template,_simulate_index_template,_simulate- un template de composants est un template qu'on cite depuis un autre : tant qu'il n'est pas lu,
composed_ofest refusé à la pose plutôt qu'appliqué à moitié. La simulation, elle, rend l'index qu'on obtiendrait — utile, et sans client qui la demande. arabic,czech,greek,thaiet les autres langues- leur chaîne demande des filtres de normalisation qui ne sont pas portés (et, pour plusieurs, un stemmer absent de
rust-stemmers). Rien n'y est mesuré : les douze langues servies le sont mot à mot, et celles-ci ne le seraient pas. char_filter- aucun mapping venu d'une instance réelle n'en a encore demandé ; c'est une brique à écrire, pas un obstacle.
- Un analyzer de type autre que
custom(french,standardparamétré…) - paramétrer un analyzer intégré (
stopwords,stem_exclusion) demande de reproduire sa composition interne exacte, qui n'est mesurée que dans sa forme par défaut. - Tout autre type (
geo_point,ip,binary…) - chacun demande son propre encodage et ses propres requêtes ; aucun n'est apparu dans les mappings des instances reprises jusqu'ici.
- Autres paramètres de champ (
null_value,doc_values,norms…) - les paramètres acceptés sont
type,analyzer,search_analyzer,fields,ignore_above,format,index,copy_toetstore; les autres sont refusés plutôt qu'acceptés sans effet, faute de quoi undoc_values: falselaisserait croire qu'un champ n'est pas triable. version/version_typeexternes- la version d'un document est gérée par ferrite ; l'imposer de l'extérieur demande de tenir un ordre que le serveur ne contrôle plus, et rien ne l'a encore réclamé.
_reindex, pipelines d'ingestion_reindexcopie d'un index vers un autre, et son intérêt est justement ce que ferrite n'a pas : une source distante, un pipeline, un script. Rien ne s'y oppose, ce n'est pas écrit — etscroll+_bulkle font aujourd'hui côté client, ce que ni_delete_by_queryni_update_by_queryne permettaient.filter,routing,index_routing,search_routingsur un alias- un alias filtré dont le filtre n'est pas appliqué rendrait précisément les documents qu'il est censé cacher ; le routage, lui, n'a rien à choisir sur un mono-shard.
GET /_cat/aliases- route absente (
no handler found) ; ses tests exigent en plush=,s=ethelpsur les_cat, que ferrite n'a pas — 10 cas de la suite d'Elastic tombent dessus. remove_indexetaddd'un alias du même nom dans le mêmePOST /_aliases- refusé en 400 (« an index or data stream exists with the same name as the alias ») : ferrite applique les alias avant les suppressions, là où ES calcule tout l'état puis l'applique — c'est pourtant l'usage même de
remove_index. GET /{index}/_aliassur un index fermé_close/_opensont hors périmètre, donc un index fermé n'existe pas ici.intervals,terms_set,script,span_*…parsing_exception: unknown query [...], avec la liste des clauses connues.collapse,knn,seq_no_primary_term,post_filter,suggest,rescore,track_scores,q,terminate_after,version,indices_boost,profile,slice,stats,ext,retriever- aucun n'est un obstacle de moteur.
search_afteretpit, qui manquaient le plus, sont servis depuis la carte 08. rest_total_hits_as_int- il change la forme de
hits.total(nombre au lieu d'objet) ; ES 8 l'accepte encore et du code venu de la 6.x/7.x s'en sert, voir [compat-es7.md](compat-es7.md). _msearch,_search/template_msearchest le plus regretté : un tableau de bord qui pose six facettes fait six appels au lieu d'un.composite,filters,nested,significant_terms,date_range,ip_range,percentile_ranks,median_absolute_deviation…filters(la sœur plurielle defilter) etcompositesont les deux qui manquent le plus ; aucune n'est un obstacle de moteur.nesteddans unnested- il faudrait un indice d'élément par niveau.
inner_hits,ignore_unmappedinner_hitsdemande de rendre l'élément qui a correspondu : ferrite le sait (c'est la colonne jumelle), il ne l'expose simplement pas.
read this bit
This is version 0.10.0, single-node, with no authentication. Anyone who can reach port 9200 can read and write every index, and there is no replica anywhere — the durability of your data is the durability of that one volume. Treat it as a search index you can rebuild from your source of truth, on a private network, and it is exactly the right size. Treat it as a database and it will disappoint you.
The search box, not the search cluster.
Most products that need search need one index, a few hundred thousand documents and a facet or two — and end up running a distributed system designed for petabytes because that’s what the client library talks to. This talks to the same library.
- sidecar
- in the same compose file as the app, on the same volume, with no capacity plan
- CI
- a service container that starts faster than the checkout step it follows
- dev environments
- a Spunto worker that comes up with search already answering
- the edge of a product
- search inside an appliance, an on-prem install, a Raspberry Pi