Get notified when a document changes in a view / Is it safe to use "_local_seq"?

#1

I would like to perform an action each time a document changes, It does not matter if it is a creation or an update. This is for specific documents in a view, not any document in the database. This topic says it’s not possible.

I am using Couchbase Lite 1.2 on iOS, with Swift.

At first I tried to use a Live Query. I am indeed notified every time the view changes, but the problem is that every document in the view is returned. I need to iterate over each row and have a mechanism to find if I already performed my action. As the database grows, the process will get slower and very inefficient.

I could register for notifications of kCBLDatabaseChangeNotification, but this means that I have to filter the changes by myself and not use the View/Query mechanism which works well.

Then I think I’ve found a working solution, but I am not sure this is safe and future-proof. I could create a view that emits documents using their _local_seq property. From what I understand, this is an Int which is auto-incremented.

view.setMapBlock("1") { doc, emit in
    guard let sequence = doc["_local_seq"] as? Int else { return }
    emit(sequence, nil)
}

I can remember somewhere the last local sequence I processed. Each time I want to process the documents, I can query the view by setting the startKey to the last local sequence and I will only get the document that have not been processed yet.

let query = allConversationsBySequenceView.createQuery()
query.startKey = start
query.inclusiveStart = false
let live = query.asLiveQuery()

And it works on my setup! But now I have some doubts:

  • Is it a good solution?
  • Is _local_seq always present in the dictionary that is given to a map function?
  • Will _local_seq always be present, or do I have a risk that it will be removed in a future release?

Thanks

1 Like
#2

After some digging, I found a two-year old topic that talks about it.

Maybe @jens can confirm that _local_seq is here to stay?

#3

The best way to detect all document changes is to observe the database-changed notification; I’m not sure why you think this is a bad solution?

LiveQuery is very convenient, but it’s expensive because the indexing and querying happens every time the database updates.

#4

Also, FYI, the technique you describe is equivalent to an all-docs query using the order-by-sequence option.

#5

Thanks @jens. Maybe I have not put enough emphasis on this, but I am not interested in all documents.

(Oh, that’s a funny quoting feature from the forum software)

My thought was if I use the “database changed” notification, I will have to apply the same logic that I have in my view map function somewhere else. Also, the database notification does not give the document content, so I have to fetch them one by one instead of relying on the view/query feature.

Does that make more sense? Should I still use the notification instead of the order-by-sequence thing?

#6

Oh, sorry I missed that!

I would still use the database-changed notification — even if you have to filter out the docs you’re interested in, it’s still more lightweight than creating a second view, because there is no persistent index being created and updated.

If you’re concerned about repeating the logic of your map function, you can factor out the test part of the map into a separate function (something like bool isDocumentInteresting(doc)), and then also call that from your observer.

But yes, _local_seq is supported and can be relied on.

#7

Woops, I got carried over other things and forgot to respond.

Thanks for the clear answer Jens.