Skip to main content

Mapping file

Each mapping version has its own JSON file. The file is a standard OpenSearch mapping object with three required top-level sections.

Required structure

{
"mappings": {
"dynamic": false,
"_meta": {
"schema_version": 0,
"jeap": {
"collection_fields": ["keywords"]
}
},
"properties": {
"search_item": { ... },
"origin": { ... },
"data": { ... }
}
}
}

dynamic: false is required — the plugin validates its presence. The three sections map to the responsibilities of the index writer service and the domain service:

SectionWritten byPurpose
search_itemjEAP Index WriterIndexing metadata: write timestamp, major and minor version.
originjEAP Index WriterReference back to the source business object.
dataDomain serviceApplication-defined business fields — this section is mapped to Java.

Collection fields

OpenSearch has no separate array mapping type: the same field mapping accepts either one value or an array. Use mappings._meta.jeap.collection_fields to declare fields that the plugin must generate as java.util.List<T>:

"_meta": {
"schema_version": 0,
"jeap": {
"collection_fields": [
"keywords",
"details.codes",
"cases.tags"
]
}
}

Paths are relative to data.properties, use the JSON snake_case field names, and descend through properties. A parent collection does not change the cardinality of its children: cases and cases.tags describe two independent collection fields.

All fields, including fields mapped as nested, are single-valued unless listed in collection_fields. This allows a nested mapping to generate either a single record or a list of records. The declaration controls the generated Java type only; OpenSearch mapping and query semantics remain defined by each field's type.

Declaring an object with sub-properties as a collection produces a build warning because OpenSearch flattens arrays of objects and loses correlation between sibling values. Use nested when that correlation must be preserved.

Requiredness, null checks, and non-empty collection checks are not expressed by this metadata.

search_item section (fixed)

"search_item": {
"type": "object",
"properties": {
"upserted_at": { "type": "date", "format": "strict_date_optional_time||epoch_millis" },
"major_version": { "type": "integer" },
"minor_version": { "type": "integer" }
}
}

This section must conform to the bundled IndexTypeMappingDescriptor.schema.json validated by the plugin.

origin section (fixed)

"origin": {
"type": "object",
"properties": {
"id": { "type": "keyword" },
"version": { "type": "keyword" },
"bp_id": { "type": "keyword" },
"tenant": { "type": "keyword" },
"created": { "type": "date", "format": "strict_date_optional_time||epoch_millis" },
"modified": { "type": "date", "format": "strict_date_optional_time||epoch_millis" },
"reference": { "type": "object", "enabled": false }
}
}

data section (application-defined)

The data section defines the business fields specific to the index type. Field names must be snake_case — the plugin rejects camelCase names at build time.

"data": {
"type": "object",
"properties": {
"document_id": { "type": "keyword" },
"document_title": { "type": "text" },
"issued_by": {
"type": "object",
"properties": {
"name": { "type": "keyword" },
"office": { "type": "keyword" }
}
},
"created_at": { "type": "date", "format": "strict_date_optional_time||epoch_millis" }
}
}

OpenSearch to Java type mapping

The plugin generates Java records from the data section. object and nested fields with sub-properties become inner records, declared inside the record of the field they belong to, at any nesting depth.

OpenSearch typeJava type
keyword, text, wildcard, constant_keywordString
integer, short, byteInteger
longLong
float, half_floatFloat
double, scaled_floatDouble
booleanBoolean
datejava.time.Instant
binaryString
object with no sub-propertiesJsonNode
object with sub-propertiesGenerated inner record
nested with no sub-propertiesJsonNode
nested with sub-propertiesGenerated inner record

Any type in collection_fields is wrapped in List, for example keyword becomes List<String> and nested with sub-properties becomes List<generated inner record>.

Fields whose JSON name differs from the Java identifier convention get a @JsonProperty annotation. For example, document_id@JsonProperty("document_id") String documentId.

object versus nested

Use nested when object values must retain correlation between their sub-fields in OpenSearch. Cardinality is independent: list the path in collection_fields for an array, or omit it for one object. Declaring object for a field that carries an array makes OpenSearch flatten the array and lose correlation between sibling values; the plugin warns about this combination.

"cases": {
"type": "nested",
"properties": {
"case_reference": { "type": "keyword" },
"control_pattern": {
"type": "object",
"properties": {
"factual_name": { "type": "text" }
}
}
}
}
public record MyTypeDataV1(
List<Cases> cases
) {

public record Cases(
@JsonProperty("case_reference") String caseReference,
@JsonProperty("control_pattern") ControlPattern controlPattern
) {

public record ControlPattern(
@JsonProperty("factual_name") String factualName
) {}
}
}