iOS: Chat implementation with pagination and handling new message arrivals

63 views
Skip to first unread message

parvez....@decurtis.com

unread,
Jun 21, 2017, 8:48:32 AM6/21/17
to Couchbase Mobile
For an iOS application backed by Couchbase Lite that is implementing a chat feature. The feature is not using CBLUIDataSource. How pagination will be implemented in it? It seems to me that we need to make use of combination of limit (always set to some constant like 10 or 15), startKey and offset on the query returning chat messages such that in its first fetch (also called first page) the startKey is empty and offset is 0. In second and subsequent fetches the startKey will be the document id from the last document in previous page result and offset is set to 1. Is this the correct approach for pagination?

The above approach corresponds to the case when user scrolls from most recent message down to the messages of prior times. How pagination will work if user start moving from first chat message at the bottom to upwards to more recent messages?

While user is scrolling the chat messages (no matter upwards or downwards), if new chat message arrives then how we will be notified of it? Do we need to add KVO over the chat message query observing the "rows" field ?

Thanks


parvez....@decurtis.com

unread,
Jun 21, 2017, 8:56:11 AM6/21/17
to Couchbase Mobile
A small change in the question offset is replaced with skip

On Wednesday, June 21, 2017 at 6:18:32 PM UTC+5:30, parvez....@decurtis.com wrote:
For an iOS application backed by Couchbase Lite that is implementing a chat feature. The feature is not using CBLUIDataSource. How pagination will be implemented in it? It seems to me that we need to make use of combination of limit (always set to some constant like 10 or 15), startKey and skip on the query returning chat messages such that in its first fetch (also called first page) the startKey is empty and skip is 0. In second and subsequent fetches the startKey will be the document id from the last document in previous page result and skip is set to 1. Is this the correct approach for pagination?

Jens Alfke

unread,
Jun 21, 2017, 11:25:10 AM6/21/17
to mobile-c...@googlegroups.com
On Jun 21, 2017, at 5:56 AM, parvez....@decurtis.com wrote:

It seems to me that we need to make use of combination of limit (always set to some constant like 10 or 15), startKey and skip on the query returning chat messages such that in its first fetch (also called first page) the startKey is empty and skip is 0. In second and subsequent fetches the startKey will be the document id from the last document in previous page result and skip is set to 1. Is this the correct approach for pagination?

10 or 15 is much too small a page size! You should be able to get hundreds or thousands of rows without noticeable delay, especially if you run the query asynchronously.
‘startKey' is a key in the view, not a document ID. (In a view for displaying chat history, the key is probably going to be the message timestamp.)
‘skip’ is the number of rows to skip. So it would be incremented by the page size, not by 1.

Updating ‘startKey’ to change pages works well if there are no duplicate keys in the view, which is pretty likely in a chat transcript. (It helps if you save the timestamps with higher resolution than seconds.) If there can be many duplicate keys, it gets a bit more complex and you have to start using ‘startKeyDocID’.

(I’m pretty sure all of this is covered in our query documentation; if the docs didn’t help you, please let us know what was unclear so we can improve them.)

The above approach corresponds to the case when user scrolls from most recent message down to the messages of prior times. How pagination will work if user start moving from first chat message at the bottom to upwards to more recent messages?

You use descending=false instead of descending=true in the query.

While user is scrolling the chat messages (no matter upwards or downwards), if new chat message arrives then how we will be notified of it? Do we need to add KVO over the chat message query observing the "rows" field ?

If you use a LiveQuery you’ll be notified via KVO when the query results change.

—Jens

Parvez Qureshi

unread,
Jun 22, 2017, 1:19:21 PM6/22/17
to mobile-c...@googlegroups.com
In the KCBLDatabaseChanfed notification's userinfo property we receive a field with key "external". What it means?


How we can know from " rows" property of CBLLIVEQUERY that what is changed in the database?

From: mobile-c...@googlegroups.com <mobile-c...@googlegroups.com> on behalf of Jens Alfke <je...@mooseyard.com>
Sent: Wednesday, June 21, 2017 8:55:09 PM
To: mobile-c...@googlegroups.com
Subject: Re: iOS: Chat implementation with pagination and handling new message arrivals
 
--
You received this message because you are subscribed to a topic in the Google Groups "Couchbase Mobile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mobile-couchbase/xmY5P1LABi0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mobile-couchba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/mobile-couchbase/8A9DF57B-8920-4F68-884C-058CC6394378%40mooseyard.com.
For more options, visit https://groups.google.com/d/optout.

Jens Alfke

unread,
Jun 22, 2017, 4:16:52 PM6/22/17
to Couchbase Mobile

On Jun 22, 2017, at 10:19 AM, Parvez Qureshi <parvez....@decurtis.com> wrote:

In the KCBLDatabaseChanfed notification's userinfo property we receive a field with key "external". What it means?

It means that one or more of the changes (in the “changes” property) come from a pull replication, as opposed to being locally-made changes.

How we can know from " rows" property of CBLLIVEQUERY that what is changed in the database?

There’s no built-in support for this; CBLLiveQuery just re-runs the query after a database change and notifies you when the results are different from the previous results. Internally it’s just calling [newResults isEqual: oldResults], so there’s no detail about what the differences are.

Most of the time you can do without the details. Just redraw the whole table view and it works OK.

There is a somewhat experimental internal class called CBLArrayDiff that you can find in the source tree. It takes two arrays and tells you how they differ in terms of a series of insertions/deletions/substitutions. This is very useful if you want to animate a table view, for instance. The implementation of this is kind of complex, based on the Wagner-Fischer algorithm that’s commonly used in ‘diff’ tools. It can become slow with large data sets but it generally behaves pretty well.

—Jens

parvez....@decurtis.com

unread,
Jun 28, 2017, 6:30:24 AM6/28/17
to Couchbase Mobile
How to integrate JSQMessageViewController with couchbase backed chat application? Since JSQMessageViewController uses its own data source so we can use Couchbase lite with it?

Priya R

unread,
Jun 28, 2017, 10:13:45 AM6/28/17
to Couchbase Mobile
I haven't used JSQMessageViewController so I spent some time looking through the class definitions. Specifically, I looked at the DataSource interface definition and this is what I'd do  :-
- The data source expects you to return objects conforming to  JSQMessageData and it looks like JSQMessage already conforms to this so you could probably just create instances of this class for your chat messages
-Basically, the model for your chat messages view is a messages array of type JSQMessage and this is what you will use as your data source

So the question is how to tie in CBLite with JSQMessage message array

For that,
a) Register for CB Lite database change notifications (or use live query).
b)  When user types message and taps on Send to send message, you will create a document in the CBL database .
c) This should trigger DB change notification 
d) When you get a notification that the CBL has changed, you can query for changes and create a corresponding JSQMessage and add it to your messages array 
e) Reload the table. Since the messages array is the data source for your table, it should reflect the changes to messages array

Similarly, when you receive messages via CB replication, when  the document is added to CBL , it  should trigger a DB change notification and you can follow the steps in (d)-(e) above

Also, the demo application  in that repo looks like a pretty good starting point ...

-Priya

parvez....@decurtis.com

unread,
Jun 30, 2017, 3:00:58 AM6/30/17
to Couchbase Mobile
In the case of kCBLDatabaseChangeNotification, we only receive documentID and an external field. How we can determine if the corresponding document is a new one (arrived from Couchbase Server)? Do we need to keep a separate collection of documentIDs to match with arrived documentID (in the notification) to determine if it is a new one?

Jens Alfke

unread,
Jun 30, 2017, 12:54:02 PM6/30/17
to mobile-c...@googlegroups.com

On Jun 30, 2017, at 12:00 AM, parvez....@decurtis.com wrote:

In the case of kCBLDatabaseChangeNotification, we only receive documentID and an external field. How we can determine if the corresponding document is a new one (arrived from Couchbase Server)? Do we need to keep a separate collection of documentIDs to match with arrived documentID (in the notification) to determine if it is a new one?

That notification provides an array of CBLDatabaseChange objects. Each of those has an ‘external’ field that indicates whether the change was made by a pull replication.

—Jens

Parvez Qureshi

unread,
Jul 1, 2017, 12:25:06 AM7/1/17
to mobile-c...@googlegroups.com
That means we need to have a logic that will check for received document ids for preexistence in a locally maintained collection to determine if document is new, updated or deleted.

Thanks
Reply all
Reply to author
Forward
0 new messages