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.
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.
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.
When finished, click the check mark, and the data table gets updated with an active filter.
At the bottom, you will find a download link that exports the objects of the currently viewed box in JSON format.
Schema Browser
You can get a detailed list of elements that make up an object type in the “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.
GraphQL
The Docker-version of ObjectBox Admin offers a pane to query the database using GraphQL.
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:
1
2
3
4
5
6
7
8
@Entity()
classShape{
@Id()
intid=0;
// An array of RGB color values that are used by this shape.
Int32List?palette;
}
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.
1
2
3
4
5
6
7
8
9
@Entity(id=1,uid=1)
classImageEmbedding:
id=Id(id=1,uid=1001)
# Link to the actual image, e.g. on Cloud storage
url=Property(str,id=2,uid=1002)
# The vector embedding for this image (created via some ML model)
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 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…
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
@Entity
publicclassImageEmbedding{
@Id
publiclongid;
// Link to the actual image, e.g. on Cloud storage
publicStringurl;
// The coordinates computed for this image (vector embedding)
publicfloat[]coordinates;
}
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! ❤️
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.
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:
1
2
3
4
5
6
7
8
9
10
11
12
void_transferFunds(Store store,List<int>ids){
finalbox=store.box<account>();
finalfrom=box.get(ids[0])!;
finalto=box.get(ids[1])!;
from.balance-=100;
to.balance+=100;
box.putMany([from,to]);
}
await store.runInTransactionAsync(TxMode.write,
_transferFunds,[accountIdFrom,accountIdTo]);
</account></int>
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 ).
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Java
@Entity
publicclassCustomer{
@Id
privatelongid;
privateObjecttag;
// TODO getter and setter
}
// Kotlin
@Entity
data classCustomer(
@Id varid:Long=0,
vartag:Any?=null
)
Then set a String tag on one customer, and an Integer tag on another customer and just put them:
1
2
3
4
5
6
7
8
9
10
11
// Java
Customer customerStrTag=newCustomer();
customerStrTag.setTag("string-tag");
Customer customerIntTag=newCustomer();
customerIntTag.setTag(1234);
box.put(customerStrTag,customerIntTag);
// Kotlin
val customerStrTag=Customer(tag="string-tag")
val customerIntTag=Customer(tag=1234)
box.put(customerStrTag,customerIntTag)
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:
1
2
3
4
5
6
7
8
9
// Java
StringstringTag=(String)
box.get(customerStrTag.getId()).getTag();
IntegerintTag=(Integer)
box.get(customerIntTag.getId()).getTag();
// Kotlin
val stringTag=box.get(customerStrTag.id).tag asString
val intTag=box.get(customerIntTag.id).tag asInt
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Java
@Entity
publicclassCustomer{
@Id
privatelongid;
privateMap<String,String>properties;
// TODO getter and setter
}
// Kotlin
@Entity
data classCustomer(
@Id varid:Long=0,
varproperties:MutableMap<String,String>?=null
)
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:
1
2
3
4
5
6
7
8
9
10
11
12
// Java
Customer customer=newCustomer();
Map<String,String>properties=newHashMap<>();
properties.put("premium","tier-1");
customer.setProperties(properties);
box.put(customer);
// Kotlin
val customer=Customer(
properties=mutableMapOf("premium"to"tier-1")
)
box.put(customer)
To query for any customers that have a premium key in their properties map, use the containsElement condition:
1
2
3
4
5
6
7
8
9
10
// Java
Query<customer>queryPremiumAll=box.query(
Customer_.properties.containsElement("premium")
).build();
// Kotlin
val queryPremiumAll=box.query(
Customer_.properties.containsElement("premium")
).build()
</customer>
Or to only match customers where the map key has a specific value, here a specific premium tier, use the containsKeyValue condition:
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.
The Android database for superfast Java / Kotlin data persistence goes 3.0. Since our first 1.0-release in 2017 (Android-first, Java), we have released C/C++, Go, Flutter/Dart, Swift bindings, as well as Data Sync and we’re thrilled that ObjectBox has been used by over 800,000 developers.
We love our Java / Kotlin community ❤️ who have been with us since day one. So, with today’s post, we’re excited to share a feature-packed new major release for Java Database alongside CRUD performance benchmarks for MongoDB Realm, Room (SQLite) and ObjectBox.
What is ObjectBox?
ObjectBox is a high performance database and an alternative to SQLite and Room. ObjectBox empowers developers to persist objects locally on Mobile and IoT devices. It’s a NoSQL ACID-compliant object database with an out-of-the-box Data Sync providing fast and easy access to decentralized edge data (Early Access).
In Kotlin, the condition methods are also available as infix functions. This can help make queries easier to read:
1
val query=box.query(User_.firstName equal"Joe").build()
Unique on conflict replace strategy
One unique property in an @Entity can now be configured to replace the object in case of a conflict (“onConflict”) when putting a new object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Kotlin
@Entity
data classExample(
@Id
varid:Long=0,
@Unique(onConflict=ConflictStrategy.REPLACE)
varuniqueKey:String?=null
)
// Java
@Entity
publicclassExample{
@Id
publiclongid;
@Unique(onConflict=ConflictStrategy.REPLACE)
StringuniqueKey;
}
This can be helpful when updating existing data with a unique ID different from the ObjectBox ID. E.g. assume an app that downloads a list of playlists where each has a modifiable title (e.g. “My Jam”) and a unique String ID (“playlist-1”). When downloading an updated version of the playlists, e.g. if the title of “playlist-1” has changed to “Old Jam”, it is now possible to just do a single put with the new data. The existing object for “playlist-1” is then deleted and replaced by the new version.
Built-in string array and map support
String array or string map properties are now supported as property types out-of-the-box. For string array properties it is now also possible to find objects where the array contains a specific item using the new containsElement condition.
We compared against the Android databases, MongoDB Realm and Room (on top of SQLite) and are happy to share that ObjectBox is still faster across all four major database operations: Create, Read, Update, Delete.
We benchmarked ObjectBox along with Room 2.3.0 using SQLite 3.22.0 and MongoDB Realm 10.6.1 on an Samsung Galaxy S9+ (Exynos) mobile phone with Android 10. All benchmarks were run 10+ times and no outliers were discovered, so we used the average for the results graph above. Find our open source benchmarking code on GitHub and as always: feel free to check them out yourself. More to come soon, follow us on Twitter or sign up to our newsletter to stay tuned (no spam ever!).
Using a fast on-device database matters
A fast local database is more than just a “nice-to-have.” It saves device resources, so you have more resources (CPU, Memory, battery) left for other resource-heavy operations. Also, a faster database allows you to keep more data locally with the device and user, thus improving privacy and data ownership by design. Keeping data locally and reducing data transferal volumes also has a significant impact on sustainability.
Sustainable Data Sync
Some data, however, you might want or need to synchronize to a backend. Reducing overhead and synchronizing data selectively, differentially, and efficiently reduces bandwidth strain, resource consumption, and cloud / Mobile Network usage – lowering the CO2 emissions too. Check out ObjectBox Data Sync, if you are interested in an out-of-the-box solution.
Get Started with ObjectBox for Java / Kotlin Today
Already an ObjectBox Android database user and ready to take your application to the next level? Check out ObjectBox Data Sync, which solves data synchronization for edge devices, out-of-the-box. It’s incredibly efficient and (you guessed it) superfast 😎
We ❤️ your Feedback
We believe, ObjectBox is super easy to use. We are on a mission to make developers’ lives better, by building developer tools that are intuitive and fun to code with. Now it’s your turn: let us know what you love, what you don’t, what do you want to see next? Share your feedback with us, or check out GitHub and up-vote the features you’d like to see next in ObjectBox.
We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.Ok