Articles
Elasticsearch Mapping Interview Questions: Nested Objects, Flattened Fields, and Query Semantics
Practice Elasticsearch mapping interview questions with object-array false matches, nested query scope, flattened fields, negation traps, and migration checks.
A product has two variants: red in size S and blue in size M. A search for red in size M returns that product. The JSON looks correct, the query has two filters, and Elasticsearch reports no error. Where did the incorrect match come from?
For Elasticsearch mapping interview questions, start with the scope of the predicate. Are you asking whether a document contains two values anywhere, whether one array element satisfies both conditions, or whether an arbitrary metadata key has a value? Mapping and query structure must preserve the same meaning.
This guide concentrates on matching boundaries, negation, and the cost of preserving relationships.
Evidence boundary: Product behavior below comes from Elastic’s official documentation. The catalog examples, expected-result tables, and recommendations are original exercises. No independently verified recent candidate report establishes that a particular employer asks these exact questions. Examples use explicit keyword fields and ordinary mappings, without synthetic-source or special subobject configuration.
Why can an object array return a false match?
Official fact: Elasticsearch has no dedicated array data type. With an ordinary object mapping, fields from an array of objects become multivalued fields, losing the association between values belonging to the same object. Elastic’s array documentation.
Consider this original document:
{
"product_id": "P1",
"variants": [
{"color": "red", "size": "S"},
{"color": "blue", "size": "M"}
]
}
For the relevant filters, think of the object mapping as exposing variants.color = [red, blue] and variants.size = [S, M]. A condition requiring red and M can find both values, even though no variant contains that pair.
The returned product is not random corruption. The indexed representation answers a different question: “Does this product have a red variant and an M variant?” That might be correct for some analytics, but it is wrong if the shopper wants to buy a red M item.
Preserving the original array in _source does not repair the indexed predicate. Explain the distinction between the document you retrieve and the structures used to execute a search. Changing the response format or filtering displayed variants afterward does not turn the original search into a correctly scoped match.
How does a nested mapping preserve the relationship?
Official fact: A nested field indexes each nested object as a separate hidden document. A nested query evaluates its inner query against those objects and returns the parent when a child matches. This preserves each array element’s independent identity for querying. Elastic’s nested field reference.
For a new disposable index, the relevant mapping body is:
{
"mappings": {
"properties": {
"product_id": {"type": "keyword"},
"variants": {
"type": "nested",
"properties": {
"color": {"type": "keyword"},
"size": {"type": "keyword"}
}
}
}
}
}
The corresponding search body puts both conditions inside one nested query:
{
"query": {
"nested": {
"path": "variants",
"score_mode": "none",
"query": {
"bool": {
"filter": [
{"term": {"variants.color": "red"}},
{"term": {"variants.size": "M"}}
]
}
},
"inner_hits": {}
}
}
}
keyword makes these exact-value predicates intentional. The exercise is about correlation, so stemming and tokenization would obscure the question. score_mode: none also makes clear that this condition selects products rather than ranking matching variants.
Use inner_hits during investigation to see which child satisfied the condition. A returned parent’s full source may still contain nonmatching variants; the parent being a hit does not mean every child matched.
Why are two nested queries not equivalent to one?
This follow-up tests whether your query preserves the intended relationship.
An outer Boolean query containing one nested query for red and a second nested query for M allows each nested query to find a different child. The mapping preserves the children, but your query has asked two independent existence questions.
Compare three original products:
| Product | Variants | Ordinary object: red AND M | One nested query: red AND M | Separate nested queries |
|---|---|---|---|---|
| P1 | red-S, blue-M | Match | No match | Match |
| P2 | red-M, blue-S | Match | Match | Match |
| P3 | green-M | No match | No match | No match |
The intended condition is “there exists one variant with red and M.” The separate-query condition is “there exists a red variant, and there exists an M variant.” The same product can satisfy the latter with two different children.
Recommended interview technique: Translate the requirement into plain English before writing DSL. Underline “same variant,” “same employment record,” or “same address” whenever fields must remain correlated. Then place those predicates within one matching scope.
If the requirement intentionally allows different children—for example, a product must offer both red and blue somewhere—separate nested queries may be appropriate. Correctness comes from matching the requirement, not from always using one particular query shape.
Where should must_not go to exclude a parent?
Now suppose a product has two sellers: one active and one banned. The requirement is “exclude any product with a banned seller.”
A nested query containing an inner must_not for banned status asks whether some seller is not banned. The active seller satisfies it, so the parent can still match.
Official fact: Elastic documents this nested-negation behavior and recommends an outer must_not to exclude documents containing a matching nested object. Nested query reference.
For a separately mapped nested sellers field with a keyword status, use this search body:
{
"query": {
"bool": {
"must_not": [
{
"nested": {
"path": "sellers",
"query": {"term": {"sellers.status": "banned"}}
}
}
]
}
}
}
The parent with both statuses is excluded. A parent with no sellers also passes this exclusion because it has no banned seller. If the business additionally requires an eligible seller to exist, add a positive nested condition defining eligibility.
Treat missing status separately, too. “Not banned” and “explicitly active” are different policies. Decide whether missing status should exclude a product rather than letting a negation expression silently choose the business rule.
When should you use flattened instead?
The word “flattened” causes confusion because ordinary object arrays are flattened internally, while flattened is also a named mapping type. Keep the ordinary object representation separate from the named mapping type.
Official fact: An ordinary flattened field maps an object’s arbitrary keys within one field mapping and indexes its leaf values as keywords. It supports basic keyword-style searches. Range queries on those untyped values use string ordering, not numeric ordering. Elastic’s flattened reference.
Original modeling example: Keep stable product fields explicitly typed, model correlated variants as nested when needed, and store a changing bag of vendor labels in metadata using flattened. Searching metadata.campaign = autumn does not need a nested child for each metadata key.
But do not put a price requiring numeric comparisons into an untyped keyword bag and assume price > 20 has numeric meaning. As strings, "100" sorts before "20". The same distinction matters for sorting and aggregations, not just filters.
Current Elastic documentation also describes explicitly mapped typed subfields under flattened; that is different from ordinary untyped leaves. Check support in your deployed version before using that capability. The examples here assume no such typed subfields and keep business-critical numeric fields explicitly mapped outside the bag.
flattened also does not recreate array-element correlation. If each label entry contains both a key and attributes that must match together, first write the required predicate. Saving mapping entries is not sufficient if it changes the answer returned to users.
What costs come with nested fields?
Preserving relationships adds work. Official fact: Each nested object creates an additional hidden Lucene document, and Elastic applies mapping limits to constrain nested usage. Exact limits and configuration support should be checked for the target deployment. Nested mapping limits.
For an original sizing estimate, 100,000 products with 20 variants each represent about 2.1 million Lucene documents: 100,000 parents plus two million nested children. That count is not a memory or latency benchmark; it only exposes why counting top-level products understates the indexed units.
An update to one variant is also not an independently addressable child-document update through the ordinary document API. Treat nested arrays as part of the parent’s indexing unit when evaluating frequent updates. Elastic’s update API describes fetching and reindexing the document; a small partial-update request does not imply proportionally small indexing work.
Recommended decision: Ask about children per parent, update frequency, result unit, required correlations, and acceptable write amplification. If variants change independently at very high rates, compare a variant-per-document model with product grouping against nested storage. That alternative changes pagination, product counts, and aggregation semantics, so it is not a free performance fix.
Are you counting variants or products?
Mapping also changes the unit counted by an aggregation. Official fact: A nested aggregation enters the nested-document scope; its document count represents nested objects. A reverse nested aggregation can move back to the parent scope.
Original follow-up: Add product P4 with two red variants: red-S and red-M. The storefront asks, “How many products offer red?” Counting matching nested variants gives two for P4, but the intended product count is one. The mapping can be correct while the aggregation still answers the wrong business question.
First select the relevant parents, enter the variants aggregation, filter the children by red, and then return to the parent scope for a product count. Keep a separate child count if the UI also needs the number of red variants. Label those two results explicitly.
Do not assume a nested query selecting parents automatically restricts every child considered by a later nested aggregation. If only matching children should contribute, express that filter within the aggregation scope too. Test a parent with one qualifying child and one nonqualifying child, then a parent with two qualifying children. Those cases expose both filter-scope mistakes and accidental overcounting.
Before optimizing the request, ask whether the result unit is a product, variant, seller, or offer. That choice belongs in the requirement alongside the matching predicate.
How would you migrate and prove the new mapping works?
Do not assume an existing object field can simply become nested in place. Elastic’s update mapping API restricts changes to existing field types. Plan a new index with explicit mappings and a controlled data migration.
Original validation plan: Seed P1, P2, and P3, execute the correlated and separate-scope queries, and assert exact parent IDs. Include the mixed active/banned seller, an empty seller list, and a missing-status seller. Test the negative cases that previously produced plausible but incorrect results.
Use an explicit refresh boundary in the disposable fixture so a missing hit is not merely a visibility delay. Inspect the actual mapping and sample indexed data rather than trusting an application-side schema declaration. Validate the snippets against the target Elasticsearch version; the truth table explains expected semantics, not a claim that a production cluster was exercised here.
For a live migration, handle writes occurring during backfill, preserve stable identifiers, verify counts and representative query results, and switch the read/write destination only after the catch-up strategy is complete. Record how to reverse the switch without discarding newer writes. Creating the replacement index is only the first step.
Sources and Further Reading
Research checked September 21, 2026. Product behavior and supported settings can vary by version and deployment.