Translating a View and Reduce in CBL1 to CBL2 Queries


#1

I’m in the process of converting some CBL View code into CBL 2 Queries, I’ve done most of the things I’ve needed already, but struggling to convert something where I use the view with a reduce function. As far as I understand it, I’ll need to do some Joins, but I’ve been scratching my head over a week now to understand your examples on Joins. I might be mistaken, but I wish you had more examples of how to convert View/Reduce stuff into queries.

I’ve got some documents of the form:

Doc 0 (doc id: forms.layouts.1|xyz):

{
    "title": "Parent form"
}

Doc 1 (doc id: forms.layouts.1|abc):

{
    "title": "Child form 1",
    "parent":"xyz"
}

Doc 2 (doc id: forms.layouts.1|cdf):

{
    "title": "Child form 2",
    "parent": "xyz"
}

Doc 3 (doc id: forms.layouts.1.project_alpha|fgh):

{
    "title": "Child form 3",
    "parent": "xyz"
}

Doc 4 (doc id: forms.layouts.1.project_beta|21z):

{
    "title": "Child form 4",
    "parent": "xyz"
}

Doc 5 (doc id: forms.layouts.1|221x):

{
    "title": "Child form 5 for another parent",
    "parent": "whatever"
}

Document ids can take two forms:

forms.layouts.{account_id}|{record_id}

forms.layouts.{account_id}.{project_id}|{record_id}

Here’s my View and Reduce blocks:

let map : CBLMapBlock = {doc,emit in
        
        guard let docId = doc["_id"] as? String else { return }
        guard docId.hasPrefix("forms.layouts.") else { return }
        guard let parent = doc["parent"] as? String else { return }

        let gid = CBUtils.groupIdFromDocumentId(docId)
        let aid = CBUtils.accountIdFromGroupdId(gid)
        let rid = CBUtils.recordIdFromDocumentId(docId)

        if let pid = Form.projectId(fromRecordId:rid)
        {
            emit("\(aid):\(pid)",parent)
        }

        emit("\(aid)",parent)
    }
    
    let reduce : CBLReduceBlock = {keys,values,rereduce in

        var res = [String:Int]()
        guard let ids = values as? [String] else { return res }
        
        for id in ids
        {
            var cnt = res[id] ?? 0
            cnt += 1
            res[id] = cnt
        }
        
        return res
    }

The output of this is essentially the number of child forms per parent form.
In CBL 1 I can query the view/reduce and get the number of children of the parent form for an account / project combination, or across the whole account (ignoring the project id).

For the example documents I showed I should be getting:

With the key: “1”:

"xyz":4
"whatever":1

With the key: “1:project_alpha”:

"xyz":3
"whatever":1

How to get something similar with CBL2 style queries?