What Elasticsearch is
TrapAn index is closer to a table than to a database. 8.0 removed mapping types, so each index has one mapping.
hash(_routing) % primaries picks a document's shard, so the primary count can't change once the index exists.text field into terms. The inverted index maps each term to the documents that hold it. A keyword field keeps the whole value as one term._id, then to its replicas. A search asks one copy of every shard for its top hits, then fetches them.TrapAn index is closer to a table than to a database. 8.0 removed mapping types, so each index has one mapping.
"number_of_shards": 3"number_of_replicas": 1PUT /logs/_settingsYou can change it any time. The primary count is fixed.hash(_routing) % primaries, where _routing defaults to the _id.POST /logs/_split/logs-split It builds a new index, because the primary count can't change.elasticsearch -E cluster.name=prod Elasticsearch moves shards onto it.TipAim for 10GB to 50GB a shard. Plan enough shards so new nodes have some to take over.
TrapA replica never shares a node with its primary. On a one-node cluster, replicas stay unassigned and health is yellow.
node.roles: [ master ]The elected master creates indices and allocates shards.node.roles: [ data ]node.roles: [ ingest ]node.roles: [ ]Every node coordinates too.TipWith no node.roles, a node takes every default role. Use dedicated roles in production.
TrapBefore 7.0, a wrong discovery. allowed split brain. 8.0 removed the setting.
TrapElasticsearch hasn't been Apache 2.0 since 2021. It's Elastic License 2.0 or SSPL, plus AGPLv3 since 2024.
PUT /users/_doc/1It overwrites the whole document if ID 1 exists.PUT /users/_create/1 It fails with 409 Conflict if the ID exists.GET /users/_doc/1POST /users/_update/1 Send the changed fields in doc.DELETE /users/_doc/1POST /_bulkPut an action line before each document. Aim for 1 to 15MB a request.POST /logs/_delete_by_query TrapAn update still rewrites the whole document. Segments never change, so Elasticsearch only marks the old version deleted.
?if_seq_no=2&if_primary_term=1 Send back the _seq_no and _primary_term you read.?version=100&version_type=external Elasticsearch writes only if your version is higher.TipOn a 409 conflict, read the document again and retry.
TrapSince 7.0 you can't check for conflicts with the internal _version. It only counts changes.
Asked in interviews
AskedExplain document versioning in Elasticsearch.?refresh=trueIt forces a refresh, which is expensive.?refresh=wait_for "refresh_interval": "30s"-1 turns it off for a bulk load.TipA refresh writes a new Lucene segment. A flush commits segments to disk and starts a new translog.
standard, the default, plus simple, whitespace, keyword and english."tokenizer": "standard""filter": ["lowercase", "stop"]Define it under analysis in the index settings.TrapToken filters run in order. Put lowercase before stop, or stop misses The.
"type": "text"Search a field word by word"type": "keyword"Match, sort or aggregate the whole value"fields": {"keyword": {"type": "keyword"}}Search name, and sort on name.keyword.Get both from one fieldTipDynamic mapping sets ignore_above: 256 on .keyword, so longer strings can't be matched exactly.
Asked in interviews
AskedWhat is the difference between text and keyword field types?GET /products/_mapping text, keyword, long, double, date, boolean, object, nested, geo_point and ip.text plus .keyword, or date if it looks like one. A whole number becomes long."dynamic": "strict"false keeps them in _source but doesn't index them.keyword"match_mapping_type": "string"Put it in a dynamic template.TipA field for every new key is a mapping explosion. An index allows 1,000 fields by default.
TrapYou can add fields, but you can't change an existing field's type. That needs a new index and a reindex.
text fields have none.text field anyway"fielddata": trueIt loads the field into the JVM heap. Use a keyword sub-field instead.TipSet "doc_values": false on a field you never sort or aggregate on. It saves disk.
Asked in interviews
AskedWhat are doc values and why do they matter?"type": "nested"Each object becomes a hidden document. Search it with a nested query."type": "join"Parent and child share a shard. has_child queries are slow.TrapElasticsearch flattens an object array. Alice rated 5 and Bob rated 1, so a search for alice with a 1 still matches.
Asked in interviews
AskedHow do you model relationships when Elasticsearch has no joins?{"match": {"title": "quick brown"}}It analyzes the text, then matches any of the terms.{"term": {"status": "active"}}It skips analysis. Use it on keyword fields, numbers and IDs.{"range": {"price": {"gte": 10}}}GET /_analyzeSend analyzer and text. It lists each token with its position.TrapA term query on a text field often finds nothing. The index holds quick and brown, not Quick Brown.
mustRequire a match that adds to the scorefilterRequire a match, skip scoringshouldRank a match highermust_notLeave out matchesTipPut exact conditions, like status, IDs and dates, in filter. Keep full-text conditions in must.
TrapWith no must or filter, at least one should must match. Otherwise should only adds score.
"boost": 2For your own formula, use function_score.?search_type=dfs_query_then_fetch It adds a round trip. Use it on small indices.TrapEach shard scores with its own term statistics by default. On small indices, scores can differ by shard.
"from": 40, "size": 20Each shard collects all earlier hits too. from + size can't pass 10,000 by default.POST /logs/_pit?keep_alive=1m A point in time (PIT). Close it when you finish."search_after": [1735689600000, 42]Pass the last hit's sort values.POST /logs/_search?scroll=1m Scroll suits exports, but not paging.Asked in interviews
AskedHow do you paginate deeply without the from and size penalty?"type": "completion"The completion suggester is the fastest. It matches the start of the inputs you index."type": "edge_ngram"Index edge n-grams. A match then works as a prefix search."type": "search_as_you_type" Query it with a bool_prefix multi_match.TrapSet search_analyzer to standard on an edge n-gram field. Otherwise Elasticsearch splits the query into n-grams too.
"type": "dense_vector"Set dims. Similarity is cosine by default."knn": {"k": 10, "num_candidates": 100}HNSW finds approximate neighbours. Raise num_candidates for accuracy."type": "semantic_text"It calls an inference endpoint when you index.TipA filter inside knn runs during the search, not after it, so you still get k hits.
Asked in interviews
AskedHow does Elasticsearch support vector and semantic search?"terms": {"field": "brand"}range and date_histogram also make buckets."avg": {"field": "price"}sum, min and max work the same way."cumulative_sum": {"buckets_path": "sales"}A pipeline aggregation, here a running total.aggs block inside the bucket aggregation.TrapThe nested aggregation isn't a sub-aggregation. It aggregates the inner documents of a nested field.
"calendar_interval": "month"Each bucket has as many days as its month."fixed_interval": "12h""min_doc_count": 1extended_bounds adds empty buckets past the data.Trapcalendar_ takes one unit, like 1d. A multiple like 2d needs fixed_interval.
Asked in interviews
AskedHow do you perform date histogram aggregations?POST /_aliasesSend a remove and an add together. Searches never see a gap."filter": {"term": {"level": "error"}}A filtered alias.PUT /products_v2Reindex copies no settings or mappings.POST /_reindex?wait_for_completion=false It runs as a task. Then swap the alias.DELETE /products_v1"type": "alias"A field alias.TipAliases also give many monthly indices one name, and keep old names working for old clients.
TrapWrites during the copy need a plan. A second pass with op_type: create adds missed documents, but not updates or deletes.
logs-* index the same settingsPUT /_index_template/logs Set index_patterns, then put settings, mappings and aliases under template.PUT /_component_template/base List them in composed_of."priority": 600The higher one wins. Built-in ones use 100.TrapPUT /_template makes a legacy template, deprecated since 7.8. Use _index_template.
Asked in interviews
AskedExplain the concept of index templates.min_age."max_primary_shard_size": "50GB""max_age": "30d"The rollover action, in the hot phase."min_age": "365d"Set it on the delete phase.node.roles: [ data_hot ]Or data_warm, data_cold, data_frozen. ILM moves older indices down the tiers.TipCold and frozen tiers can use searchable snapshots, which need no replicas. Frozen reads them straight from the repository.
PUT /_snapshot/my_backup A shared filesystem, S3, Azure Blob Storage or Google Cloud Storage.PUT /_snapshot/my_backup/snap-1 Each one is incremental, so frequent snapshots stay cheap.POST /_snapshot/my_backup/snap-1/_restore Set rename_pattern if the names clash with live indices.PUT /_slm/policy/nightly Snapshot lifecycle management (SLM).TrapCopying the data folders is not a backup. Snapshots are the only supported way.
GET /_cluster/health Yellow means a replica is unassigned. Red means a primary is.GET /_cat/indices?vGET /_cat/nodes?vGET /_cluster/allocation/explain GET /_nodes/statsTipAlert on heap above 85%, disk above 85%, slow searches and failed indexing.
TrapAt 85% disk, Elasticsearch puts no new shards on a node. At 95%, it blocks writes to that node's indices.
Asked in interviews
AskedHow do you monitor Elasticsearch cluster health and performance?xpack.security.enabled: true .xpack.security.transport.ssl.enabled: truexpack.security.http.ssl.enabled: truePOST /_security/api_key logs-*POST /_security/role/logs_reader A role can also hide fields and filter documents.TipTurn on audit logging. Encrypt the disks too, since Elasticsearch doesn't encrypt data at rest.
TrapNever expose port 9200 to the internet. Keep the cluster on a private network behind a firewall.
Asked in interviews
AskedHow do you secure an Elasticsearch cluster?"number_of_replicas": 0Turn refresh off too. Until you add replicas back, a node failure can lose data."translog.durability": "async"A crash can lose acknowledged writes.?routing=user42Index the documents with the same value.bootstrap.memory_lock: trueLeave the heap size to Elasticsearch, or keep it under 32GB.TipIndex and search tuning often conflict. Replicas raise search throughput but slow every write.
"index.search.slowlog.threshold.query.warn": "2s"The slow log is off by default."profile": trueIt adds overhead, so compare parts, not totals.GET /_nodes/hot_threads ing{"wildcard": {"name": "*ing"}}A leading wildcard reads every term. Index n-grams instead.TipScripts in sorts or script_score run for every document. Compute those values at index time.
Asked in interviews
AskedHow do you debug a slow search query in Elasticsearch?Nothing matches. Try a shorter word, or clear the search.
With Pro, you can:
Already have Pro? Sign in