MongoDB Data Mapping

Ensure smooth data synchronization between MongoDB and ObjectBox by correctly mapping data and types.

The data model used by ObjectBox defines types, which are mapped to MongoDB collections. Similarly, the properties of a type are mapped to fields (keys) inside a MongoDB document. Thus, you should ensure that the ObjectBox data model matches the MongoDB schema. For example, if you have an existing MongoDB database, ensure to match the names when you create the ObjectBox model.

Some MongoDB field types like strings match ObjectBox types and thus do not need additional mapping information. More specialized types need "external types" to be defined in the ObjectBox data model to match the MongoDB field types. This page explains how to do this.

Objects and Documents

When you compare the data structure of simple data elements, the difference is not significant. Without nested data, the main difference you will note is the ID type.

Comparison of ObjectBox Object and MongoDB Document structure
Figure 1: ObjectBox Object vs. MongoDB Document (Simplified)

Note: nested documents are supported via the ObjectBox "flex properties" type or JSON strings. See the section below for details.

ID mapping

ObjectBox Sync automatically maps IDs when syncing with an external system like MongoDB. This way, you can use the native IDs in each system: 64-bit integer IDs in ObjectBox and, for example, 12-byte object IDs in MongoDB. This also means that the MongoDB ID is not present in ObjectBox objects and vice versa.

Special ID types

If you only use standard MongoDB object IDs, you do not need to do anything special. This section is only relevant if you want to use other ID types.

ObjectBox supports most common ID types offered by MongoDB. IDs of incoming documents from MongoDB are automatically detected and mapped to ObjectBox local IDs. This mapping is persisted, and thus any change made on the ObjectBox side can be mapped back to the initial ID type and value.

For newly created (inserted) objects on the ObjectBox side, a new MongoDB object ID (OID) is created by default. You can customize the MongoDB ID types in the ObjectBox data model: for the ID property, define an "external property type" on the ID property. Then, ObjectBox will create a new UUID-based ID for the MongoDB document.

@ExternalType(ExternalPropertyType.UUID)
private byte[] externalId;

Recommended types for IDs: UUID (UUIDv7), UUIDString (UUIDv7 as string), UUIDV4, UUIDV4String.

The following table shows the supported ID types:

MongoDB type
Incoming from MongoDB
IDs for new documents created in ObjectBox

Object ID

This is the default type

UUID (Binary with UUID subtype)

External types: Uuid (V7) or UuidV4

String

External types: UuidString (V7) or UuidV4String

Binary

Uses default MongoDB Object ID

Int64

Uses default MongoDB Object ID

Int32

Uses default MongoDB Object ID

Property/Field type mapping

Standard Types

Most standard types do not need an explicit mapping between ObjectBox (also used in your programming language) and MongoDB:

  • Strings

  • Integers: integers with 8, 16 or 32 bits map to MongoDB Int32, integers with 64 bits map to MongoDB Int64

  • Floating point numbers: double and float types both map to MongoDB Double

  • Booleans

  • Dates: Date maps to MongoDB Date, DateNano maps to MongoDB Int64

  • Arrays/Vectors of standard types map to a MongoDB array (all elements have the same type, heterogeneous types are discussed below)

Special Types

MongoDB also has some special types, that do not directly map to ObjectBox types. To disambiguate, ObjectBox allows you to define "external property types" in the data model (also used in the ID mapping above). For example, a string on the ObjectBox (your programming language) side can represent several types on the MongoDB side string, a UUID, or a few more. The following table shows the possible mappings:

ObjectBox Property Type
External Property Type
MongoDB Field Type

Bytes (byte vector)

-

Binary

Bytes (byte vector)

Decimal128

Decimal128

Bytes (byte vector)

MongoId

ObjectId

Bytes (byte vector)

MongoBinary

Binary/dynamic subtype

Bytes (byte vector)

Uuid

Binary/UUID

Bytes (byte vector)

UuidV4

Binary/UUID

Flex

-

Object

Flex

FlexMap

Object

Flex

FlexVector

Array

Long (64-bit int)

-

Int64

Long (64-bit int)

MongoTimestamp

Timestamp

String

-

String

String

JavaScript

JavaScript (Code)

String

JsonToNative

Object/Array

String

MongoId

ObjectId

String

Uuid

Binary/UUID

String

UuidV4

Binary/UUID

String Vector

-

Array (strings only)

String Vector

MongoRegex

Regex

The external property types are defined as part of your data model on the "client" side using the external property types annotation. Check the docs for your specific ObjectBox API.

Notes:

  • The Flex type is discussed in more detail in separate sections below (nested documents and arrays). Note that the flex type is not available on all ObjectBox platforms yet.

  • JsonToNative is discussed in more detail in separate sections below (nested documents and arrays).

  • MongoBinary: on the ObjectBox side, this is encoded as a byte vector with a 4 bytes prefix. The first 3 bytes are reserved and must be zero. The 4th byte defines the MongoDB binary sub type. After the 4 bytes prefix, the actual binary content follows.

  • MongoRegex: on the ObjectBox a string vector with exactly 2 elements is created. The first element is the regex pattern, the second element is the regex options (index 0: pattern, index 1: options).

  • MongoDB has the following deprecated types, which are currently not supported: Undefined, DBPointer, Symbol. If you rely on these types, please contact us. We may provide at least some support for these types.

  • IDs and relations are documented separately on this page.

To-One Relations

If you want to learn more about ObjectBox relations, check the relation documentation.

ObjectBox Sync also automatically maps IDs used in relations.

Consider ObjectBox to-one relations, which have a single relation property pointing to another object using a 64-bit integer ID. This becomes a reference field in MongoDB's document containing the MongoDB object ID (OID). See the following illustration for an example:

To-One Relationship Example: motherId mapping
Figure 2: To-One Relationship Example (motherId)

The supported ID types also apply for relations. For example, if a "Person" document uses a UUID as its _id field value, relations to it would also use the UUID as the relation ID on the MongoDB side.

Many-to-Many Relations

Many-to-many relations work a bit differently. As illustrated in the table above, many-to-many relations work differently in ObjectBox and MongoDB. For mapping between them, the following rules apply:

  • On the MongoDB side, many-to-many relations are stored as an array of ID references:

    • The IDs are stored inside the document "owning" the relationship.

    • The owning side of a relationship is always the same type (collection).

    • If you want to, you can make this relation bidirectional by adding IDs to the "target side" of the relationship. Do not make this visible in the ObjectBox data model.

  • On the ObjectBox side, its native many-to-many relationships are used:

    • They are bidirectional, e.g. you can define it on the owning and target side.

    • They can be updated efficiently without touching the object.

    • They can be used in queries to link types (aka join).

As to-many relations consist of ID values, all supported types can be used. In theory, different ID types can be used in the same to-many relation. However, it is usually good practice to stick to a single ID type per MongoDB collection if possible.

Nested Documents

MongoDB documents are key-value pairs. And because values may be documents, it is possible to have documents inside a document. This is known as "nested documents", "embedded documents" or "sub documents". ObjectBox offers two ways to handle this: flex properties and JSON strings.

The following table shows the current support for the two variants per programming language:

Programming Language
Flex
JSON String

Java

Kotlin

Swift

Dart/Flutter

C and C++

(✅)*

*) C and C++ via API (Generator support is pending)

Flex Properties Mapping

To map nested documents with flex properties, you define maps with string keys in your entity definition directly on the ObjectBox side:

@Nullable Map<String, Object> stringMap;

Flex properties characteristics and notes:

  • Directly access the data as maps in your code

  • Nested documents and arrays are supported

  • The precision of integer types on the MongoDB side may change, e.g. Int32 to Long (64-bit)

  • The order of keys is not preserved

JSON String Mapping

An alternative is to store the nested document as a JSON string on the ObjectBox side. This is done with a standard string property and the external property type "JSON to native". Thus, on the ObjectBox side, you can use a JSON API of your choice to access the nested document.

@ExternalType(ExternalPropertyType.JSON_TO_NATIVE)
private String myNestedDocumentJson;

JSON string characteristics and notes:

  • JSON API to access the data

  • Nested documents and arrays are supported

  • The precision of integer types on the MongoDB side may change, e.g. Int32 to Long (64-bit)

  • The order of keys is preserved

Heterogeneous Arrays

Homogeneous arrays (all values of the same type) are mapped automatically by ObjectBox.

Similar to nested documents, arrays with values of different types can be used inside a MongoDB document. This is supported in ObjectBox and MongoDB. The same rules apply as for nested documents.

Flex Properties Mapping

To map nested arrays, you define lists in your entity definition directly on the ObjectBox side:

@Nullable List<Object> myArray;

JSON String Mapping

Exactly the same approach as for nested documents applies (see above). Instead of a JSON object, a JSON array is used.

Last updated

Was this helpful?