Remove old channels on docs after sync function change

Couchbase version: Couchbase Server Community Edition 7.6.4 build 5146
Sync Gateway version: “Couchbase Sync Gateway/2.8.2(1;4df7a2d) CE”

We have an application that uses mobile (iOS & Android) and web clients for the users to update data.

We defined a sync function to assign and require assorted channel names with each doc, based on their contents. The mobile apps use some of these to restrict what data is synced via Sync Gateway Lite, rather than syncing all of the data, which takes far too long.

Because of a bug in our sync function (not in production yet, thankfully), a bunch of documents got assigned to a channel that they should not belong to, caused unnecessary data to sync.

e.g. This is a query on one doc showing meta().id, licensee_id (our internal data), doc_type (ours), OBJECT_NAMES(meta().xattrs._sync.channels), and voided (ours):
{
"a_id": "a-001D6743-FBF2-4A0C-9AD7-49727E82B3CA",
"b_licensee_id": "licensee-dev",
"c_doc_type": “Asset”,
"d_channels": [
"B$licensee-dev",
"V$licensee-dev",
"licensee-dev"
],
“f_voided”: “true”
}

The bug resulted in the “B$licensee-dev” channel being added to this document. I fixed the sync function (I think), restarted Sync Gateway, and then did an offline/resync/online operation via the REST Admin API, but the document (and others like it) still has this channel present.

My updated sync function:

“sync”: `function (doc, oldDoc) {
		if (doc.doc_type) {
			if (doc.licensee_id === undefined) {
				channel("!");
			} else {
				var requireChannels = new Array();
				var l_channel = doc.licensee_id;
				channel(l_channel);
				requireChannels.push(l_channel);

			if ((doc.voided !== undefined) && doc.voided) {
			  var v_channel = "V$" + doc.licensee_id;
			  channel(v_channel);
			  requireChannels.push(v_channel);
			}

			if ((doc.doc_type === 'Licensee') || (doc.doc_type === 'Customer')) {
			  var b_channel = "B$" + l_channel;
			  channel(b_channel);
			  requireChannels.push(b_channel);
			} else if (doc.customer !== undefined) {
			  var c_channel = "C$" + doc.customer;
			  channel(c_channel);
			  requireChannels.push(c_channel);
			}
			requireAccess(requireChannels);
		}
	}
}`,

If I’ve done my sync function right, only documents with doc_type = ‘Licensee’ or ‘Customer’ should have the “B$…” channel.

Am I doing something wrong? Am I misunderstanding how the channels/sync function work? Or have I messed something up in the sync function?

I added logging to the sync function to ensure that it was processing things correctly and could not find any case where documents with the incorrect doc_type were assigned to the “B$…” channel, so it seems like the channel assignment is left over from before. Is there anyway to remove it?

In addition, am I querying the Channels info properly? The full N1QL statement is

select licensee_id as b_licensee_id, count(*)
from `bucket-licensees`
where
doc_type is valued
and
doc_type in [
'Asset',
'Inspection',
'Map'
]
and
(voided is not valued OR not voided)
and
ANY c IN object_names(meta().xattrs._sync.channels) SATISFIES c like "B$%" end
group by licensee_id
order by licensee_id

Is there any way to update the channels metadata via N1QL?