When creating a partial index using view the resulting code for mapper in JavaScript simply will not work:
CREATE INDEX meta_id ON `beer-sample`(META().id) WHERE META().id <> "" USING VIEW;
Query results:
{
"results": []
}
The resulting view meta_id
within design document _design/ddl_meta_id
is coded like this:
function (doc, meta) {
if (meta.type != "json") return;
var stringToUtf8Bytes = function (str) {
var utf8 = unescape(encodeURIComponent(str));
var bytes = [];
for (var i = 0; i < str.length; ++i) {
bytes.push(str.charCodeAt(i));
}
return bytes;
};
var indexFormattedValue = function (val) {
if (val === null) {
return [64];
} else if (typeof val == "boolean") {
return [96, val];
} else if (typeof val == "number") {
return [128, val];
} else if (typeof val == "string") {
return [160, stringToUtf8Bytes(val)];
} else if (typeof val == "object") {
if (val instanceof Array) {
return [192, val];
} else {
var innerKeys = [];
for (var k in val) {
innerKeys.push(k);
}
innerKeys.sort()
var innerVals = [];
for (var i in innerKeys) {
if (typeof val[innerKeys[i]] == "object" &&
(val[innerKeys[i]] === null || Object.keys(val[innerKeys[i]]).length === 0)) {
if (val[innerKeys[i]] === null) {
innerVals.push([64])
} else if (Object.keys(val[innerKeys[i]]).length === 0) {
innerVals.push([224, [[], []]]);
}
} else {
innerVals.push(indexFormattedValue(val[innerKeys[i]]));
}
}
return [224, [innerKeys, innerVals]];
}
} else {
return undefined;
}
};
var key1 = indexFormattedValue(doc.meta.id);
var key = [key1];
var pos = key.indexOf(undefined);
if (pos == 0) {
return;
} else if (pos > 0) {
key.splice(pos)
}
if (! (doc.meta.id == "")) {
emit(key, null);
}
}
// salt: 1031304417
Note the lines
var key1 = indexFormattedValue(doc.meta.id);
and
if (! (doc.meta.id == "")) {
Here meta.id
must be used, not doc.meta.id
, which is just incorrect.
I tested this on Couchbase versions 4.5.0, 4.6.2, and 5.0.0 Beta 2, and did not found a corresponding issue in the bugtracker.
Actually, this is a huge issue for me as my Couchbase installation contains up to 7.5 billion documents, and using a full index (USING VIEW) requires prohibitive amount of memory. Using a GSI-powered index would require massive network exchange between the nodes, as no data locality is provided in that case, and the index node will become a bottleneck as GSI index is not distributed, and all that is not desirable as I try to have latencies as low as possible (250 microseconds now).
Is there a workaround or a misunderstanding? Simply changing the automatically generated view doesn’t help, as the index engine, obviously, verifies the content of the mapper and refuses to use a modified one.