This multipart blog will help you build an end-to-end mobile application using the industry-leading features of Couchbase Lite. State of the art end-to-end, scalable and production-grade applications include the following features:
-
- An embedded database – storing data locally reduces network trips to a centralized database for every activity on the device. This goes a long way in improving the user experience.
- Synchronization with other peer mobile devices and with a centralized server.Â
- Advanced analytic capabilities, full-text search and machine learning on the device.
Since there’s a lot to cover, we’ve split this project into three parts. Part 1 showcases the process for building a mobile application that leverages Couchbase Lite and uses it as an embedded database to store data. Part 2 (this post) shows how to run Full-Text Search (FTS) on the device. And part 3 will showcase the process of syncing the data with peers and a centralized Couchbase server.
What is Couchbase Mobile?Â
Couchbase is an award-winning distributed NoSQL cloud database. It delivers unmatched versatility, performance, scalability, and financial value across cloud, on-premises, hybrid, distributed cloud, and edge computing deployments.
Mobile/edge deployments are an essential part of the digital ecosystem that Couchbase Mobile addresses. Couchbase Mobile includes:
-
- Embedded Couchbase Lite database for edge devices
- High-performance Sync Gateway for peer to peer and centralized server synchronization
- Edge data centers powered by Couchbase Server can be deployed on the cloud, on-prem or in local edge data centers.
Mobile application overview
The code for this demo application is available in my Couchbase Mobile GitHub repository. Download the file Rateit.zip and extract the files to your local folder.
Alternatively, you can follow the instructions in this blog to build the app from scratch.
The app’s functionality is divided into three partsÂ
-
- Send rating requests
- Receive rating requests from others
- View the rated request returned from others
To get a deeper understanding of the various components of the app, please refer to part 1, where we send/receive rating requests.
Adding Full-Text search
In this example, we add a simple search button and the code to add an inverted index (used by search systems) that takes user input and displays relevant results.
Getting Started: Review CBLite Documentation
Please review the documentation to understand the various components of a Couchbase Lite database application. I create a brand new database for this app when the application is invoked for the first time. Alternatively, the app can also use a pre-built database.
The steps to embed the database are found in the Couchbase Lite documentation. Review each of the sections to learn to:
-
- create and open a database
- write a document into the embedded database
- write queries to retrieve the document
- expire or delete a document
- build Full-Text Search indexesÂ
- make an FTS search expression
- create a query incorporating the search expression
App building prerequisites
This app has been built for Android devices using the following software and hardware prerequisites that you need to be aware of:
-
- You need to understand the basics of building apps with Android Studio and programming in Java.
- This demo app and related screenshots come from building the app on a macOS computer.
- We use (freely available) Android Studio 2020.3 to build mobile apps for Android devices.Â
- Couchbase Lite version 3.0.0-beta02 is used. The required libraries will be embedded in the code and there is no need to download the software manually to your desktop.
Understanding the layout
Layout files are XML files that describe the mobile application screen. For example, activity_main.xml has the SEND TO, MESSAGE, SUBJECT fields in addition to the two listviews that show received and incoming requests.Â
It also defines which function to invoke when the CLICK TO SEND RATING REQUEST, RECEIVED RATING REQUESTS and INCOMING RATING REQUESTS buttons are pressed. The XML code can be manually written or auto-generated by setting the attributes in the attributes section of the designer. Here, we add a search input to the center of the layout:
Reviewing the codeÂ
There is one code file that we update to add the search logic to the application, Mainactivity.java.
Locate Mainactivity.java under the java -> com.example.rateit folder and paste the following code inside the class MainAcivity. The new code is added to the earlier example in part 1 – it is found on line 8 and lines 12-27 below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
public void receivedata( View view ) throws CouchbaseLiteException {   Context context = this;   CouchbaseLite.init(context);   userArray.clear();   DatabaseConfiguration config = new DatabaseConfiguration();   config.setDirectory(context.getFilesDir().getAbsolutePath());   Database database = null;   File dbFile = new File(context.getFilesDir(), "rateitdb");   try { database = new Database("rateitdb", config); } catch (CouchbaseLiteException e) { e.printStackTrace(); }   if (!dbFile.exists()) {     database.createIndex("descFTSIndex", IndexBuilder.fullTextIndex(FullTextIndexItem.property("URL")));   }   SearchView search = (SearchView) findViewById(R.id.searchView);   Expression searchExp = FullTextExpression.index("descFTSIndex").match(String.valueOf(search.getQuery())) ;   Query query = null;   if (search.getQuery().toString().trim().isEmpty()) {     query = (Query) QueryBuilder.select(SelectResult.all()).from(DataSource.database(database))         .where(Expression.property("to").equalTo(Expression.string("rangana"))             .and(Expression.property("type").equalTo(Expression.string("received"))));   } else {     query = (Query) QueryBuilder.select(SelectResult.all()).from(DataSource.database(database))         .where(Expression.property("to").equalTo(Expression.string("rangana"))             .and(Expression.property("type").equalTo(Expression.string("received")))             .and(searchExp));   }     int numrows = query.execute().allResults().size();   Toast.makeText(getApplicationContext(), "num rows:::"+ numrows , Toast.LENGTH_LONG).show();   try {     query.execute().allResults().forEach(result -> {       Dictionary thisDocsProps = result.getDictionary(0);       String sendto = thisDocsProps.getString("sendto").trim();       String URL = thisDocsProps.getString("URL").trim();       String rating = thisDocsProps.getString("rating").trim();       float ratingstars = thisDocsProps.getFloat("ratingstars");       int stars = (int) ratingstars;       rating = String.valueOf(thisDocsProps.getFloat("ratingstars"));       userArray.add(new User(sendto, URL, rating,ratingstars));     });   } catch (CouchbaseLiteException e) {     e.printStackTrace();   }   userAdapter = new UserCustomAdapter(MainActivity.this, R.layout.customlayout, userArray);   userList = (ListView) findViewById(R.id.listView);   userList.setItemsCanFocus(false);   userList.setAdapter(userAdapter);   userList.setOnItemClickListener(new OnItemClickListener() {     @Override     public void onItemClick(AdapterView<?> parent, View v, final int position, long id) {       Log.i("List View Clicked", "**********");       Toast.makeText(MainActivity.this, "List View Clicked:" + position, Toast.LENGTH_LONG).show();     }   });   database.close(); } |
The receivedata functions get activated when RECEIVED RATING REQUESTS is clicked. It displays all the rating requests received by executing a query against the local database to get the records.Â
It lets you put in a rating and creates a JSON record with the rating. When the RATE button is clicked, it writes the request back to the database with a document type of rated. If the DELETE button is clicked, the record is deleted by setting the document’s time to live (TTL) to expire.
The new code sections function as follows:
-
- We first add an FTS index if the database file does not exist, indicating first-time entry into the app.
- Build the search expression if the user enters a search string
- Build the query using the search expression and run it
Wiring up the layout
The following code needs to be added to activity_main.xml. It adds the search button and its label:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<SearchView    android:id="@+id/searchView"    android:layout_width="226dp"    android:layout_height="40dp"    android:layout_marginStart="4dp"    android:layout_marginEnd="8dp"    android:layout_marginBottom="4dp"    android:background="@color/white"    app:layout_constraintBottom_toTopOf="@+id/listView"    app:layout_constraintEnd_toEndOf="parent"    app:layout_constraintStart_toEndOf="@+id/textView4"    app:layout_constraintTop_toBottomOf="@+id/Received" /> <TextView    android:id="@+id/textView4"    android:layout_width="158dp"    android:layout_height="38dp"    android:layout_marginStart="10dp"    android:layout_marginBottom="4dp"    android:background="#7BE67F"    android:backgroundTint="#7BE67F"    android:fontFamily="sans-serif-black"    android:gravity="center"    android:text="Search Text"    android:textAllCaps="true"    android:textStyle="bold"    app:layout_constraintBottom_toTopOf="@+id/listView"    app:layout_constraintStart_toStartOf="parent"    app:layout_constraintTop_toBottomOf="@+id/Received" /> |
Compiling the codeÂ
Once all the code has been updated, click on Build → ReBuild Project. Once it succeeds, click on Build → Run.
You will be asked to choose the emulator the first time you run the app, e.g., select the NEXUS 5X API 25 like I did. Once the run is complete, the main page will look like this:
You have now successfully deployed the code into the emulator of your choice. When the user enters a part of the URL string, the relevant results are displayed.
Next steps
This is the second part of the blog series, Building a Mobile Application with Couchbase, which focuses on a complete end-to-end mobile solution. The first part showed how to create an app that uses an embedded Couchbase Lite database to store, retrieve and delete documents stored locally on the device.Â
Part 2 added the ability to do text-based searches, and the third and final part of this series will add peer-to-peer syncing and syncing to a centralized database.
The primary resources referenced in this post included:
- Part 1 – Building a Mobile Application with Couchbase
- GitHub repository – including Rateit app project code
- Couchbase Mobile – product information
- Couchbase Lite documentation
- Android Studio