Learn Couchbase Lite in 5 Minutes and follow the CRUD
By Matteo Sist, Mobile Tech Lead, @MOLO17
One of the key ingredients in learning to make a great mobile app is to use a good database. So, in this article we will show how to easy it is to integrate Couchbase Lite in an iOS app.
What is Couchbase Lite? Couchbase Lite is the mobile SDK of the Couchbase Mobile suite that allows developers to easily integrate a NoSQL database into mobile applications.
This blog will go through the CRUD operations (create, read, update, delete), providing details plus tips and tricks for each of the required steps, and highlight one of my favorite features, Sync Gateway.
C as Create
The first step is to create a document with Couchbase. Couchbase has one method to create a document, saveDocument. That method accepts two parameters. The first is the document ( CouchbaseLiteSwift.MutableDocument) to be saved, and the second is an optional parameter ( CouchbaseLiteSwift.ConcurrencyControl ) that gives users the choice to resolve possible conflicts automatically or throw an exception to allow users to resolve the conflict manually. The default value is “LastWriteWins“.
How to use saveDocument method?
First, we need a database instance ( CouchbaseLiteSwift.Database ), so just initiate a new database:
1 2 3 4 5 |
do { database = try Database(name: "DatabaseName") } catch { fatalError("Error opening database") } |
Then we need to create the document we want to save. So, create a new document CouchbaseLiteSwift.MutableDocument and add some fields:
1 2 3 4 5 |
let doc = MutableDocument(id: "MyUniqueDocumentIdentifier") doc.setString("Mickey", forKey: "name") doc.setString("Mouse", forKey: "surname") doc.setInt(91, forKey: "age") doc.setString("Contact", forKey: "type") |
Finally, just save it:
1 2 3 4 5 |
do { try database.saveDocument(doc, concurrencyControl: .lastWriteWins) } catch { fatalError("Error saving document") } |
As you can see, creating and saving a document within Couchbase is really simple and intuitive.
Tips and Tricks to Learn with Couchbase Lite
– Typing: In the document I added a field named type doc.setString("Contact", forKey: "type") . This is a trick that allows you to easily split a document into types and facilitates read operations. Later I will demonstrate how to use this field.
– Id: You don’t need to provide an id when you create a document. It’s an optional field, and if you don’t, Couchbase generates a UUID for you.
– Document creation: If you want, you can create a document from a dictionary (or a key-value map) by simply passing the dictionary as a parameter on the document’s constructor.
R as Read
Now that we have created our first document we also want to read it and display it in a list. There are two ways to retrieve a document:
- Get by id
- Query
Get by id
To retrieve a document using its id we first need a database instance for a read operation.
1 2 3 4 5 |
do { database = try Database(name: "DatabaseName") } catch { fatalError("Error opening database") } |
Then we can use the method document that needs the id of the document in order to retrieve it. The return type of this method is an optional document object (CouchbaseLiteSwift.Document?) that will be nil if the document doesn’t exist.
1 |
let doc = database.document(withID: "MyUniqueDocumentIdentifier") |
Query
As for the get by id operation, we need an instance of the database for the query as well.
1 2 3 4 5 |
do { database = try Database(name: "DatabaseName") } catch { fatalError("Error opening database") } |
The next step is to create the query. To do this we need to use the metalanguage **N1QL**. N1QL, Couchbase’s query language that extends SQL to JSON data, allows users to define a query with a SQL-like syntax on a NoSQL database. See the example below.
1 2 3 4 |
let query = QueryBuilder .select(SelectResult.all()) .from(DataSource.database(database)) .where(Expression.property("type").equalTo(Expression.string("Contact"))) |
In this way, we defined a simple query that searched all documents (with all fields, of course) from the database where the field “type” is equal to “Contact”.
Now, we just have to run the query and we will receive a result set containing all the documents that observe the query options.
1 2 3 4 5 |
do { result = try query.execute() } catch { fatalError("Invalid query") } |
The object result conforms to the iterator protocol, so it can be iterated to get each document and do stuff. The result returned by the query is a snapshot of the data at the moment of the execution. The document changes made afterward will not be considered.
Tips and Tricks to Learn with Couchbase Lite
– Query listener: Couchbase also provides another method to execute queries that allow users to not only retrieve data from the built query but also listen for future changes. Doing this is as simple as the first method. Take a look!
1 2 3 |
let token = query.addChangeListener { queryChange in result = queryChange.results?.allResults() } |
The listener will be invoked every time the documents included in the query result change. The token returned from the addChangeListener
methods can be used to stop listening as follows:
1 |
query.removeChangeListener(withToken: token) |
– Document conversion: As for the creation, you can easily convert a document to a dictionary (and vice versa) using toDictionary() method.
U as Update
Now that we are able to create and read documents to Couchbase, lets update our document.
Updating a document is very similar to creating one. You only need to get a document to update, then update it, and save it again. Let see how.
Initiate the database:
1 2 3 4 5 |
do { database = try Database(name: "DatabaseName") } catch { fatalError("Error opening database") } |
Retrieve the document to update:
1 |
let doc = database.document(withID: "MyUniqueDocumentIdentifier") |
Edit it.
1 2 |
let docToUpdate = doc.toMutable() docToUpdate.setString("Male", forKey: "gender") |
And of course, save it:
1 2 3 4 5 |
do { try database.saveDocument(docToUpdate, concurrencyControl: .lastWriteWins) } catch { fatalError("Error updating document") } |
D as Delete
Last but not least, perhaps you want to delete some documents, here’s how that can be done.
As always, we need the database.
1 2 3 4 5 |
do { database = try Database(name: "DatabaseName") } catch { fatalError("Error opening database") } |
Similar to the update operation, we should retrieve the document to delete. So, you will use the document by id method.
1 |
let doc = database.document(withID: "MyUniqueDocumentIdentifier") |
Now we can use the delete method to delete a document. As with saveDocument, we can choose to resolve conflicts manually or automatically.
1 2 3 4 5 |
do { try database.deleteDocument(doc, concurrencyControl: .lastWriteWins) } catch { fatalError("Error deleting document") } |
Couchbase Sync Gateway is as easy to learn as Couchbase Lite
Now we are able to integrate Couchbase Lite into our apps using CRUD:
- Create a document
- Read a document (or many) with real-time updates if we want
- Update a document (not so different than creation)
- Delete a document
But there’s more. Couchbase provides another wonderful feature: Sync Gateway
Sync
Sync is one of my favorite functionalities of Couchbase because it is as simple as it is effective. Couchbase Lite provides this functionality in order to configure a remote database.
Let’s go deep into the code.
In addition to our database, we need another object: the replicator.
1 2 3 4 5 |
do { database = try Database(name: DatabaseName) } catch { fatalError("Error opening database") } |
What I need in order to initiate a replicator object (CouchbaseLiteSwift.Replicator) is a configuration object where the only mandatory field is the url of the Sync Gateway.
The other optional fields include replicatorType, where users can choose if the replication should work up, in, down, or both. Another field is continuous, a flag that allow users to configure whether or not replication should be run one time or continuously.
1 2 3 4 5 6 |
let targetEndpoint = URLEndpoint(url: "ws://localhost:4984/bucketname/") let replConfig = ReplicatorConfiguration(database: database, target: targetEndpoint) replConfig.replicatorType = .pushAndPull replConfig.continuous = true replConfig.authenticator = BasicAuthenticator(username: Username, password: Password) replicator = Replicator(config: replConfig) |
With the replicator object we need to only start the replication.
1 |
replicator.start() |
Or stop the replication.
1 |
replicator.stop() |
Tips and Tricks to Learn with Sync
– Listen replication status: For the query as well as for the replication we can add a listener to receive changes of replication status. Below is the code.
1 2 3 |
let token = replicator.addChangeListener { changes in status = changes.status } |
As for the queries, the token should be used to remove the listener from the replicator.
1 |
replicator.removeChangeListener(withToken: token) |
Conclusion, Couchbase Lite is Easy to Learn
Couchbase Lite, as a part of Couchbase Mobile suite, is a powerful arrow in the quiver of a mobile developer. It’s easy to learn, and in this article, we only showcased a small part of its potential, so my advice is to go deeper into Couchbase functionalities that will allow you to easily integrate and take full control of the database that supports your mobile apps.
About Matteo Sist, @MOLO17
Matteo started collaborating with MOLO17 as an Android Developer when he was in high school (via an Information Technology course). Recruited in 2015, he joined the Mobile Development Team taking the role of key Developer for both iOS and Android platforms. Skilled in languages for native mobile app development, ranging from Java and Objective-C to the most recents Kotlin and Swift, he designed and developed several successful solutions for mobile devices targeted at consumers and enterprises. In 2016, he became Tech Lead managing the mobile app development team, and in 2019, he co-founded MobileBridge (a MOLO17 sister company).