Partial set index (#14087)

* partial index test

* cleanup

* remove line

* background true

* whitespace

* test: fix invite/pending removal
This commit is contained in:
Barış Uşaklı
2026-03-11 23:49:22 -04:00
committed by GitHub
parent 25f6088f52
commit 79fe0902fe
5 changed files with 67 additions and 19 deletions

View File

@@ -86,6 +86,9 @@ mongoModule.createIndices = async function () {
const collection = mongoModule.client.collection('objects');
await collection.createIndex({ _key: 1, score: -1 }, { background: true });
await collection.createIndex({ _key: 1, value: -1 }, { background: true, unique: true, sparse: true });
await collection.createIndex(
{ members: 1, _key: 1}, { background: true, partialFilterExpression: { members: { $exists: true } } }
);
await collection.createIndex({ expireAt: 1 }, { expireAfterSeconds: 0, background: true });
winston.info('[database] Checking database indices done!');
};

View File

@@ -115,7 +115,7 @@ module.exports = function (module) {
await module.client.collection('objects').bulkWrite([
{ updateMany: { filter: { _key: filterKey }, update: update } },
{ deleteMany: { filter: { _key: filterKey, members: { $size: 0 } } } },
{ deleteMany: { filter: { _key: filterKey, members: [] } } },
], { ordered: true });
}
@@ -128,8 +128,9 @@ module.exports = function (module) {
const item = await module.client.collection('objects').findOne({
_key: key, members: value,
}, {
projection: { _id: 0, members: 0 },
projection: { _id: 0, _key: 1},
});
return item !== null && item !== undefined;
};
@@ -137,15 +138,31 @@ module.exports = function (module) {
if (!key || !Array.isArray(values) || !values.length) {
return [];
}
values = values.map(v => helpers.valueToString(v));
const stringValues = values.map(v => helpers.valueToString(v));
const result = await module.client.collection('objects').findOne({
_key: key,
}, {
projection: { _id: 0, _key: 0 },
});
const membersSet = new Set(result && Array.isArray(result.members) ? result.members : []);
return values.map(v => membersSet.has(v));
const pipeline = [
{
$match: {
_key: key,
members: { $in: stringValues, $exists: true }, // Trigger the partial index
},
},
{
$project: {
_id: 0,
results: {
$map: {
input: stringValues,
as: 'val',
in: { $in: ['$$val', '$members'] },
},
},
},
},
];
const [doc] = await module.client.collection('objects').aggregate(pipeline).toArray();
return doc ? doc.results : values.map(() => false);
};
module.isMemberOfSets = async function (sets, value) {
@@ -157,7 +174,7 @@ module.exports = function (module) {
const result = await module.client.collection('objects').find({
_key: { $in: sets }, members: value,
}, {
projection: { _id: 0, members: 0 },
projection: { _id: 0, _key: 1 },
}).toArray();
const map = {};
@@ -176,7 +193,7 @@ module.exports = function (module) {
const data = await module.client.collection('objects').findOne({
_key: key,
}, {
projection: { _id: 0, _key: 0 },
projection: { _id: 0, members: 1 },
});
return data ? data.members : [];
};

View File

@@ -393,13 +393,13 @@ module.exports = function (module) {
return [];
}
const arrayOfKeys = keys.length > 1;
const projection = { _id: 0, value: 1 };
const projection = arrayOfKeys ?
{ _id: 0, _key: 1, value: 1} :
{ _id: 0, value: 1 };
if (withScores) {
projection.score = 1;
}
if (arrayOfKeys) {
projection._key = 1;
}
const data = await module.client.collection('objects').find({
_key: arrayOfKeys ? { $in: keys } : keys[0],
}, { projection: projection })

View File

@@ -54,9 +54,15 @@ module.exports = function (Groups) {
if (!Array.isArray(groupNames)) {
groupNames = [groupNames];
}
const sets = [];
groupNames.forEach(groupName => sets.push(`group:${groupName}:pending`, `group:${groupName}:invited`));
await db.setsRemove(sets, uid);
const sets = [
...groupNames.map(g => `group:${g}:pending`),
...groupNames.map(g => `group:${g}:invited`),
];
const isMembers = await db.isMemberOfSets(sets, uid);
const toRemoveSets = sets.filter((set, index) => isMembers[index]);
if (toRemoveSets.length) {
await db.setsRemove(toRemoveSets, uid);
}
};
Groups.invite = async function (groupName, uids) {

View File

@@ -0,0 +1,22 @@
'use strict';
const db = module.parent.require('./database');
module.exports = {
name: 'Add a partial index on set members',
timestamp: Date.UTC(2026, 2, 11),
method: async function () {
const nconf = require.main.require('nconf');
const isMongo = nconf.get('database') === 'mongo';
if (!isMongo) {
return;
}
await db.client.collection('objects').createIndex(
{ members: 1, _key: 1 },
{ background: true, partialFilterExpression: { members: { $exists: true } } },
);
},
};