The Embedded Database for C++ and C

The Embedded Database for C++ and C

After 6 years and 21 incremental “zero dot” releases, we are excited to announce the first major release of ObjectBox, the high-performance embedded database for C++ and C. As a faster alternative to SQLite, ObjectBox delivers more than just speed – it’s object-oriented, highly efficient, and offers advanced features like data synchronization and vector search. It is the perfect choice for on-device databases, especially in resource-constrained environments or in cases with real-time requirements.

What is ObjectBox?

ObjectBox is a free embedded database designed for object persistence. With “object” referring to instances of C++ structs or classes, it is built for objects from scratch with zero overhead — no SQL or ORM layer is involved, resulting in outstanding object performance.

The ObjectBox C++ database offers advanced features, such as relations and ACID transactions, to ensure data consistency at all times. Store your data privately on-device across a wide range of hardware, from low-profile ARM platforms and mobile devices to high-speed servers. It’s a great fit for edge devices, iOS or Android apps, and server backends. Plus, ObjectBox is multi-platform (any POSIX will do, e.g. iOS, Android, Linux, Windows, or QNX) and multi-language: e.g., on mobile, you can work with Kotlin, Java or Swift objects. This cross-platform compatibility is no coincidence, as ObjectBox Sync will seamlessly synchronize data across devices and platforms.

Why should C and C++ Developers care?

ObjectBox deeply integrates with C and C++. Persisting C or C++ structs is as simple as a single line of code, with no need to interact with unfamiliar database APIs that disrupt the natural flow of C++. There’s also no data transformation (e.g. SQL, rows & columns) required, and interacting with the database feels seamless and intuitive.

As a C or C++ developer, you likely value performance. ObjectBox delivers exceptional speed (at least we haven’t tested against a faster DB yet). Having several 100,000s CRUD operations per second on commodity hardware is no sweat. Our unique advantage is that, if you want to, you can read raw objects from “mmapped” memory (directly from disk!). This offers true “zero copy” data access without any throttling layers between you and the data.

Finally, CMake support makes integration straightforward, starting with FetchContent support so you can easily get the library. But there’s more: we offer code generation for entity structs, which takes only a single CMake command.

“ObjectBox++”: A quick Walk-Through

Once ObjectBox is set up for CMake, the first step is to define the data model using FlatBuffers schema files. FlatBuffers is a building block within ObjectBox and is also widely used in the industry. For those familiar with Protocol Buffers, FlatBuffers are its parser-less (i.e., faster) cousin. Here’s an example of a “Task” entity defined in a file named “task.fbs”:

And with that file, you can generate code using the following CMake command:

Among other things, code generation creates a C++ struct for Task data, which is used to interact with the ObjectBox API. The struct is a straightforward C++ representation of the data model:

The code generation also provides some internal “glue code” including the method create_obx_model() that defines the data model internally. With this, you can open the store and insert a task object in just three lines of code:

And that’s all it takes to get a database running in C++. This snippet essentially covers the basics of the getting started guide and this example project on GitHub.

Vector Embeddings for C++ AI Applications

Even if you don’t have an immediate use case, ObjectBox is fully equipped for vectors and AI applications. As a “vector database,” ObjectBox is ready for use in high-dimensional vector similarity searches, employing the HNSW algorithm for highly scalable performance beyond millions of vectors.

Vectors can represent semantics within a context (e.g. objects in a picture) or even documents and paragraphs to “capture” their meaning. This is typically used for RAG (Retrieval-Augmented Generation) applications that interact with LLMs. Basically, RAG allows AI to work with specific data, e.g. documents of a department or company and thus individualizes the created content.

To quickly illustrate vector search, imagine a database of cities including their location as a 2-dimensional vector. To enable nearest neighbor search, all you need to do is to define a HNSW index on the location property, which enables the nearestNeighbors query condition used like this:

For more details, refer to the vector search doc pages or the full city vector search example on GitHub.

store.close(); // Some closing words

This release marks an important milestone for ObjectBox, delivering significant improvements in speed, usability, and features. We’re excited to see how these enhancements will help you create even better, feature-rich applications.

There’s so much to explore! Please follow the links to dive deeper into topics like queries, relations, transactions, and, of course, ObjectBox Sync.

As always, we’re here to listen to your feedback and are committed to continually evolving ObjectBox to meet your needs. Don’t hesitate to reach out to us at any time.

P.S. Are you looking for a new job? We have a vacant C++ position to build the future of ObjectBox with us. We are looking forward to receiving your application! 🙂

Data Viewer for Objects – announcing ObjectBox Admin

Data Viewer for Objects – announcing ObjectBox Admin

ObjectBox Admin (Docker container) allows you to analyze ObjectBox databases that run on desktop and server machines. Releasing ObjectBox Admin as a standalone Docker image makes it possible to run Admin on a larger number of platforms.

ObjectBox Admin is available as a Linux x86_64 Docker image, which runs on all common platforms including Windows and macOS. We offer a convenience script (objectbox-admin.sh) but it’s also simple enough to run it via plain Docker. See the docs for details, or get started by following this short tutorial.

Data Browser

The ObjectBox Admin Web App comprises a menu on the left (Data, Schema, Status, GraphQL…) and the corresponding content pane on the right-hand side.

ObjectBox Admin Web App (Data, Schema, Status, GraphQL...)

The data browser provides a table of objects of a specific type. By clicking on the Type we can select an entity type for viewing its entity objects.

WebAdmin_Data_Type

Next to the type selection is a small filter icon (the dashed triangle right of the type selection).

When selected, a query editor pops up that allows to filter data by adding a Property/Operator/Value expression.

ObjectBox Admin Filtering

When finished, click the check mark, and the data table gets updated with an active filter.

Data Filter

At the bottom, you will find a download link that exports the objects of the currently viewed box in JSON format.

DownloadDataAsJson

Schema Browser

You can get a detailed list of elements that make up an object type in the “Schema” pane.

Schema pane

In accordance with the “Data” pane, you can click on Type to select the schema of a specific entity type of your database.

Status

Base level database and ObjectBox Admin information can be viewed on the “Status” pane.

Status pane

GraphQL

The Docker-version of ObjectBox Admin offers a pane to query the database using GraphQL.

GraphQL Data Browser

Vector Database Release for Flutter / Dart + Python

Vector Database Release for Flutter / Dart + Python

The Flutter / Dart and Python binding of our database now enable “vector types”. In both languages these are more commonly referred to as “lists” and now you are able to efficiently store lists of numeric types, i.e. integers and floating point numbers (aka “vectors / vector embeddings”). Native support for that is crucial for data intensive applications, especially in the field of AI.

What are Vector embeddings? Multi-dimensional vectors are a central building block for AI applications. And accordingly, the ability to store vectors to add long-term memory to your AI applications (e.g. via vector databases) is gaining importance. This is what the ObjectBox database now supports natively.

Dart example code

Let’s assume some shapes that use a palette of RGB colors. This allows the shape to reference colors by their index. An entity for this might look like this:

Python example code

Python is the number one programming language for AI. So let’s assume having an Image class that contains an URL to point to the content (e.g. JPEG/PNG images) and additionally a vector embedding. The latter are supplied by a ML model and contain a list of 32-bit floating points.

There is more…

The support for vector types is not the only new feature. E.g. ObjectBox Flutter database comes with several fixes and our Python database binding now also supports date types. For details, please check the changelog for Dart DB vector release or Python DB vector release.

Vector types (aka arrays) added with ObjectBox Java 3.6 release

Vector types (aka arrays) added with ObjectBox Java 3.6 release

Vector embeddings (multi-dimensional vectors) are a central building block for AI applications. And accordingly, the ability to store vectors to add long-term memory to your AI applications (e.g. via vector databases) is gaining importance. Sounds fancy, but for the basic use cases, this simply boils down to “arrays of floats” for developers. And this is exactly what ObjectBox database now supports natively. If you want to use vectors on the edge, e.g. in a mobile app or on an embedded device, when offline, independent from an Internet connection, removing the unknown latency, try it…

See the release notes for all new features this release brings.

Code Examples

Let’s start with a simple example: let’s assume some shapes that use a palette of RGB colors. An entity for this might look like this:

We can now create a query to find all shapes that use a certain color:

Another typical use case is the embedding of certain types of data, like text, audio or images, as vector coordinates. To store such a vector embedding, in the following example we store the floating point coordinates that were computed by a machine learning model for an image together with a reference to the actual image:

Ready to go?

To update to this release, change the version of objectbox-gradle-plugin to 3.6.0.

To add ObjectBox database to your JVM or Android project read our Getting Started guide.
As always, we look forward to your feedback on GitHub or via our anonymous feedback form and hope you have a great time building apps with ObjectBox! ❤️

New async APIs in ObjectBox database 2.0.0 for Flutter/Dart

New async APIs in ObjectBox database 2.0.0 for Flutter/Dart

ObjectBox Flutter database reached 2.0 today – with new async APIs.

This release has major improvements when using ObjectBox with asynchronous programming in Dart. Notably, the Box API has added async variants of methods to get and put one or more objects.

Let’s take the example from the package README and make it async:

The Query API also has added async variants of methods to find matching objects. Let’s make the query example async as well:

Behind the scenes, these use the existing async API provided by Store which runs the operation on a worker isolate. With this release we have made additional improvements that allow it to be used with objects that contain relations (ToOne and ToMany). This made us comfortable to offer it through the new async convenience methods on Box and Query mentioned above.

Sometimes, it is favorable to bundle multiple database operations and execute them “at once”. This is what runInTransactionAsync() is for.  It allows to use the synchronous APIs and wrap them in a single, asynchronous transaction. For example, let’s look at transferring funds between two bank accounts. The fund can safely be transferred from one account to another by reading the current balances, deducting the amount from one account and adding the amount to another account:

This is more efficient than calling multiple async operations and further offers transactional safety as ObjectBox offers ACID semantics.

Ready to go? To upgrade to this major release run flutter pub upgrade objectbox --major-versions (or for Dart Native apps dart pub upgrade objectbox --major-versions ).

To add ObjectBox database to your Flutter project read our Getting Started guide. Also, if you are interested to know how ObjectBox compares to competitors, check out this 2023 overview and comparison of Flutter databases article.

As always, we look forward to your feedback on GitHub or via our anonymous feedback form and hope you have a great time building apps with ObjectBox!

ObjectBox Database Java 3.1 – Flex type

ObjectBox Database Java 3.1 – Flex type

We are happy to announce version 3.1 of ObjectBox for Java and Kotlin. The major feature of this version is the new Flex type. For a long time, ObjectBox worked on rigid data schemas, and we think that this is a good thing. Knowing what your data looks like is a feature – similar to programming languages that are statically typed. Fixed schemas make data handling more predictable and robust. Nevertheless, sometimes there are use cases which require flexible data structures. ObjectBox 3.1 allows exactly this.

Flex properties

Expanding on the string and flexible map support in 3.0.0, this release adds support for Flex properties where the type must not be known at compile time. To add a Flex property to an entity use Object in Java and Any? in Kotlin. Then at runtime store any of the supported types.

For example, assume a customer entity with a tag property:

Then set a String tag on one customer, and an Integer tag on another customer and just put them:

When getting the customer from its box the original type is restored. For simplicity the below example just casts the tag to the expected type:

A Flex property can be not justString or Integer. Supported types are all integers (Byte, Short, Integer, Long), floating point numbers (Float, Double), String and byte arrays.

It can also hold a List<Object> or a Map<String, Object> of those types. Lists and maps can be nested.

Behind the scenes Flex properties use a FlexBuffer converter to store the property value, so some limitations apply. See the FlexObjectConverter class documentation for details.

Query for map keys and values

If the Flex property contains integers or strings, or a list or map of those types, it’s also possible to do queries. For example, take this customer entity with a properties String to String map:

Why is properties not of type Object? ObjectBox supports using Map<String, String> (or Map<String, Object>) directly and will still create a Flex property behind the scenes.

Then put a customer with a premium property:

To query for any customers that have a premium key in their properties map, use the containsElement condition:

Or to only match customers where the map key has a specific value, here a specific premium tier, use the containsKeyValue condition:

What’s next?

ObjectBox database is free to use. Check out our docs and this video tutorial to get started today.

We strive to bring joy to mobile developers and appreciate all kinds feedback, both positive and negative. You can always raise an issue on GitHub or post a question on Stackoverflow. Otherwise, star the ObjectBox  Java database GitHub repo and up-vote the features you’d like to see in the next release.