How to sort documents?

Hi all, I’m using CBL lite 1.3 in my iOS app. I am creating CBLView to fetch the data from data base. My view emitting two keys one is “name” and another one is “updatedDate”. I have to sort the docs by “name” or “updatedDate” based on user requirement. For this I wrote the code like below.
My view is
{
let getCustView = Constants.appDeleRef.database.viewNamed(“customersByUD”)

    getCustView.setMapBlock({ (doc, emit) -> Void in
        if doc["documentType"] as! String == NSStringFromClass(CustomerModel.self) && doc["isActive"] as? NSNumber == NSNumber(value: true as Bool) {
            emit(doc["updatedDate"]!,nil)
            emit(doc["name"]!,nil)
        }
    }, version: "1")

}

My creating Query code is
{
let query = Constants.appDeleRef.database.viewNamed(“customersByUD”).createQuery()
let sortDesc : NSSortDescriptor = NSSortDescriptor(key: “name”, ascending: true)
query.sortDescriptors = [sortDesc]
query.skip = UInt(skipIndex)
query.limit = UInt(Constants.kLimitRecords)

let result : [CBLQueryRow] = try! query!.run().allObjects as! [CBLQueryRow]
}

When I run the code my app gets crashed at bottom line which is query.run and generating the below error message. Help me how to solve this problem.

Terminating app due to uncaught exception ‘NSUnknownKeyException’, reason: ‘[<CBLQueryRow 0x15e35eb0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key name.’

The key-paths used for sorting are interpreted relative to the CBLQueryRow object, so they need to be prefixed with key. or value., as discussed in the API docs for the sortDescriptors property:

/** An optional array of NSSortDescriptor objects; overrides the default by-key ordering.
    Key-paths are interpreted relative to a CBLQueryRow object, so they should start with
    "value" to refer to the value, or "key" to refer to the key.
    A limited form of array indexing is supported, so you can refer to "key[1]" or "value[0]" if
    the key or value are arrays. This only works with indexes from 0 to 3. */
@property (copy, nullable) CBLArrayOf(NSSortDescriptor*)* sortDescriptors;

However, your view has some other problems: every document appears in the index twice, under two keys (one its name and the other its updatedDate), and there’s no way to easily tell which keys are names and which dates. Also, doing an in-memory sort with sortDescriptors is going to slow the query down a lot; ideally you want to use the index’s natural key ordering.

I suggest defining two views. One of them emits the doc’s updatedDate and the other emits its name. Then you query the first view if you want to sort by date, and the second if you want to sort by name. You won’t have to use sortDescriptors at all.

Oh, and another alternative is to use the CBLQueryBuilder class, an alternative API that offers a much more CoreData-like query experience where you specify your search criteria, sort order, and values to return; and CBL will construct the view and query for you under the hood. It’s Mac/iOS only so it’s not in the official cross-platform docs, but you can find information in the Doxygen docs or in CBLQueryBuilder.h.

Thank you @jens. I will create two views one for name and other for updatedDate. Till now I am using CBLQueryBuilder only. Day by day my database is getting bigger(nearly my database has 1Lakh documents till now it may have 2Lakhs after one year), then getting data with CBLQueryBuilder will become slow. That is why I want to use CBLView and QueryObject.

I don’t know what a Lakh is…

Why would using QueryBuilder get slow?

A Lakh is a 1 with five 0s, as I understand it. It’s a million divided by 10. It’s also a common term in India, but uncommon for those of us in the U.S. :slight_smile: