In a perfect world we’d always have a fast, reliable network connection on our mobile devices. Unfortunately, whether you’re driving through the middle of nowhere, surrounded by thousands of other people using their phones, or even in an area that should be a prime location for data, it’s inevitable that you’ll encounter connectivity issues. Luckily, problems like this can be mitigated by storing data locally.
Enter: Embedded Databases.
If you’re unfamiliar with the mobile and IoT (or as the kids are calling it these days, the edge) database landscape you’ll likely head straight to your favorite search engine to investigate the options.
Spoiler alert... there’s a lot.
And while there are a plethora of options for you to choose from, unfortunately, like so many other topics in tech, there’s no silver bullet that’s going to cure all your “edge ailments”. There are, however, solutions that stand out among the rest. One of those is Couchbase.
Couchbase, Inc., at its core, is a company that offers a distributed NoSQL database that can be hosted locally, on premises, or within all the major cloud providers. OK, great, but what does that have to do with mobile and IoT?
Couchbase Mobile extends Couchbase to that glorious edge by providing the ability to securely manage and synchronize data from any cloud/server to every mobile device with three major pieces:
As previously mentioned, Couchbase Lite is an embedded lightweight, NoSQL document-oriented, sync-able database engine. While relational databases are made up a collection of tables filled with rows of information, document databases store data in JSON blobs like the following:
{
"name": "Rob",
"age": 34,
"type": "person"
}
Storing information in documents provides flexibility and scalability advantages that are particularly helpful when used within mobile and IoT applications.
That's the gist of Couchbase Lite but you're probably wondering, where's the beef? What is Couchbase Lite supported on, and how can you use it? Couchbase Lite is supported on iOS, Android, Xamarin, IoT apps, and provides a variety of easy to implement features that make creating truly resilient apps a piece of cake. So let's dive in!
Couchbase Lite supports all the CRUD operations you'd expect from a database solution. Below is a simple example of creating and saving a MutableDocument.
Swift (iOS)
let doc = MutableDocument()
.setString("person", forKey: "type")
.setString("Rob", forKey: "name")
.setInt(34, forKey: "age")
try database.saveDocument(doc)
Java (Android)
MutableDocument doc = new MutableDocument();
newTask.setString("type", "person");
newTask.setString("name", "Rob");
newTask.setInt("age", 34);
try {
database.save(doc);
} catch (CouchbaseLiteException e) {
Log.e(TAG, e.toString());
}
C# (Xamarin)
using (var doc = new MutableDocument("person::1"))
{
doc.SetString("type", "person");
doc.SetString("name", "Rob");
doc.SetInt("age", 34);
db.Save(doc);
}
Couchbase Lite queries have changed significantly. Instead of the map/reduce views used in 1.x, they’re now based on expressions, of the form "return ____ from documents where ____, ordered by ____", with semantics based on Couchbase’s N1QL query language.
There are several parts to specifying a query:
Below is a simple query used to retrieve all "person" documents from a Couchbase Lite database.
Swift (iOS)
let query = QueryBuilder
.select(SelectResult.all())
.from(DataSource.database(database))
.where(Expression.property("type").equalTo(Expression.string("person"))))
Java (Android)
Query query = QueryBuilder
.select(SelectResult.all())
.from(DataSource.database(database))
.where(Expression.property("type").equalTo(Expression.string("person"))));
C# (Xamarin)
var query = QueryBuilder.Select(SelectResult.All())
.From(DataSource.Database(db))
.Where(Expression.Property("type").EqualTo(Expression.String("person"))));
The next step in querying on Couchbase Mobile revolves around live queries. Live queries stays active and monitor the database for changes. A live query is a great way to build reactive user interfaces, especially table/list views, that keep themselves up to date.
By simply adding a listener to a query you'll be able to receive real-time updates to your Couchbase Lite database.
Swift (iOS)
let token = query.addChangeListener { (change) in
for result in change.results! {
print(result.keys)
}
Java (Android)
ListenerToken token = query.addChangeListener(change -> {
for (Result result: change.getResults()) {
Log.d(TAG, "results: " + result.getKeys());
}
});
C# (Xamarin)
var token = query.AddChangeListener((sender, args) =>
{
var allResult = args.Results.AllResults();
foreach (var result in allResult) {
Console.WriteLine(result.Keys);
}
});
Full Text Search (FTS) lets you create, manage, and query specially purposed indexes, defined on documents within a Couchbase Lite database. FTS provides extensive capabilities for natural-language querying.
do {
let index = IndexBuilder.fullTextIndex(items: FullTextIndexItem.property("name")).ignoreAccents(false)
try database.createIndex(index, withName: "nameFTSIndex")
} catch let error {
print(error.localizedDescription)
}
database.createIndex(
"nameFTSIndex",
IndexBuilder.fullTextIndex(FullTextIndexItem.property("name")).ignoreAccents(false));
var index = IndexBuilder.FullTextIndex(FullTextIndexItem.Property("name")).IgnoreAccents(false);
db.CreateIndex("nameFTSIndex", index);
Once an index is created, an FTS query on the property that is being indexed can be constructed and executed. The FTS criteria is defined as a FullTextExpression. The left-hand side is the full-text index to use and the right-hand side is the pattern to match.
Swift (iOS)
let whereClause = FullTextExpression.index("nameFTSIndex").match("'buy'")
let query = QueryBuilder
.select(SelectResult.expression(Meta.id))
.from(DataSource.database(database))
.where(whereClause)
do {
for result in try query.execute() {
print("document id \(result.string(at: 0)!)")
}
} catch let error {
print(error.localizedDescription)
}
Java (Android)
Expression whereClause = FullTextExpression.index("nameFTSIndex").match("buy");
Query ftsQuery = QueryBuilder.select(SelectResult.expression(Meta.id))
.from(DataSource.database(database))
.where(whereClause);
ResultSet ftsQueryResult = ftsQuery.execute();
for (Result result : ftsQueryResult) {
Log.i(
TAG,
String.format("document properties %s", result.getString(0)));
}
C# (Xamarin)
var whereClause = FullTextExpression.Index("nameFTSIndex").Match("'buy'");
using (var query = QueryBuilder.Select(SelectResult.Expression(Meta.ID))
.From(DataSource.Database(db))
.Where(whereClause)) {
foreach (var result in query.Execute()) {
Console.WriteLine($"Document id {result.GetString(0)}");
}
}
Predictive Querying enables Couchbase Lite queries to use machine learning, by providing query functions that can process document data (properties or blobs) via trained machine learning models.
Consider an image classifier model that takes a picture as input and outputs a label and probability.
Couchbase Lite predictive queries allows you to integrate the ML model, and run a prediction query. For more information and samples check out the latest documentation for iOS, Android, and Xamarin.
Peer-to-peer sync allows devices running Couchbase Lite to directly synchronize data with each other. As part of this, Couchbase Lite is responsible for storing the data and keeping track of the data exchange, but isn’t responsible for the data transfer itself.
Note: Sending and receiving data must be handled by the platform APIs or a third party framework.
Sync Gateway is a horizontally scalable web server that securely manages the access control and synchronization of data between Couchbase Lite and Couchbase Server.
For most mobile developers, it comes as no surprise that creating synchronization solutions can be a pain. After all, there's a lot that goes into creating something that can handle things like:
Luckily, Sync Gateway covers all of those and more!
Since Couchbase Lite 2.0 (released in 2018), conflicts are automatically resolved. Seriously. AUTOMATICALLY.
The configuration file determines the runtime behavior, including server configuration and the database or a set of databases, that Sync Gateway can interact with.
Configuration files can be as simple or complex as you need them to be in. Below is simple example of a Sync Gateway configuration file.
{
"logging": {
"console": {
"log_level": "debug",
"log_keys": ["*"],
"color_enabled": false
}
},
"databases": {
"couchdraw": {
"server": "http://localhost:8091",
"bucket": "couchdraw",
"username": "couchdraw_user",
"password": "password",
"num_index_replicas": 0,
"enable_shared_bucket_access": true,
"import_docs": "continuous",
"users": { "GUEST": { "disabled": false, "admin_channels": ["*"] } },
"allow_conflicts": false,
"revs_limit": 20
}
}
}
To learn more about Sync Gateway configuration files take a look at the full documentation here!
Sync Gateway supports several avenues of authentication.
Sync Gateway uses channels to make it easy to share a database between a large number of users and control access to the database. Channels are the intermediaries between documents and users. Every document in the database belongs to a set of channels, and every user is allowed to access a set of channels. You can use channels to:
Couchbase Server is an open source, distributed, NoSQL document-oriented engagement database. It specializes in providing low-latency data management for interactive web, mobile, and IoT applications.
Couchbase Lite through Sync Gateway, though not a strict requirement, seamlessly integrates with Couchbase Server to provide a complete end-to-end solution on the edge.
If you'd like to know more about how use Couchbase Mobile within your mobile or IoT app consider checking out recent tutorials for iOS, Android, and Xamarin put out by the Couchbase team.
Also, if you're interesting in learning more about the latest and greatest features of Couchbase Mobile check out the newest episode of Gone Mobile!