mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-03-18 02:20:49 +01:00
Partial set index (#14087)
* partial index test * cleanup * remove line * background true * whitespace * test: fix invite/pending removal
This commit is contained in:
@@ -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!');
|
||||
};
|
||||
|
||||
@@ -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 : [];
|
||||
};
|
||||
|
||||
@@ -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 })
|
||||
|
||||
@@ -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) {
|
||||
|
||||
22
src/upgrades/4.10.0/mongodb-set-members-index.js
Normal file
22
src/upgrades/4.10.0/mongodb-set-members-index.js
Normal 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 } } },
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user