diff --git a/src/database/mongo/sorted.js b/src/database/mongo/sorted.js index d73ee9f50d..6ad7152bf2 100644 --- a/src/database/mongo/sorted.js +++ b/src/database/mongo/sorted.js @@ -330,7 +330,10 @@ module.exports = function (db, module) { if (!Array.isArray(keys) || !keys.length) { return []; } - const data = await db.collection('objects').find({ _key: { $in: keys } }, { projection: { _id: 0, score: 0 } }).sort({ score: 1 }).toArray(); + + const data = await db.collection('objects').find({ + _key: keys.length === 1 ? keys[0] : { $in: keys }, + }, { projection: { _id: 0, score: 0 } }).sort({ score: 1 }).toArray(); var sets = {}; data.forEach(function (set) { diff --git a/src/groups/join.js b/src/groups/join.js index a7b5e18351..1a64c3ca08 100644 --- a/src/groups/join.js +++ b/src/groups/join.js @@ -6,6 +6,7 @@ const winston = require('winston'); const db = require('../database'); const user = require('../user'); const plugins = require('../plugins'); +const cache = require('../cache'); module.exports = function (Groups) { Groups.join = async function (groupNames, uid) { @@ -48,6 +49,7 @@ module.exports = function (Groups) { await Promise.all(promises); Groups.clearCache(uid, groupsToJoin); + cache.del(groupsToJoin.map(name => 'group:' + name + ':members')); const groupData = await Groups.getGroupsFields(groupsToJoin, ['name', 'hidden', 'memberCount']); const visibleGroups = groupData.filter(groupData => groupData && !groupData.hidden); diff --git a/src/groups/leave.js b/src/groups/leave.js index 719039ba6b..ca19d08950 100644 --- a/src/groups/leave.js +++ b/src/groups/leave.js @@ -3,6 +3,7 @@ const db = require('../database'); const user = require('../user'); const plugins = require('../plugins'); +const cache = require('../cache'); module.exports = function (Groups) { Groups.leave = async function (groupNames, uid) { @@ -30,6 +31,7 @@ module.exports = function (Groups) { ]); Groups.clearCache(uid, groupsToLeave); + cache.del(groupsToLeave.map(name => 'group:' + name + ':members')); const groupData = await Groups.getGroupsFields(groupsToLeave, ['name', 'hidden', 'memberCount']); if (!groupData) { diff --git a/src/groups/membership.js b/src/groups/membership.js index a746148c15..0b2cf51662 100644 --- a/src/groups/membership.js +++ b/src/groups/membership.js @@ -5,6 +5,8 @@ const _ = require('lodash'); const db = require('../database'); const user = require('../user'); +const cache = require('../cache'); + module.exports = function (Groups) { Groups.getMembers = async function (groupName, start, stop) { return await db.getSortedSetRevRange('group:' + groupName + ':members', start, stop); @@ -109,7 +111,7 @@ module.exports = function (Groups) { }; Groups.isMemberOfGroupList = async function (uid, groupListKey) { - let groupNames = await db.getSortedSetRange('group:' + groupListKey + ':members', 0, -1); + let groupNames = await getGroupNames(groupListKey); groupNames = Groups.removeEphemeralGroups(groupNames); if (!groupNames.length) { return false; @@ -120,8 +122,7 @@ module.exports = function (Groups) { }; Groups.isMemberOfGroupsList = async function (uid, groupListKeys) { - const sets = groupListKeys.map(groupName => 'group:' + groupName + ':members'); - const members = await db.getSortedSetsMembers(sets); + const members = await getGroupNames(groupListKeys); let uniqueGroups = _.uniq(_.flatten(members)); uniqueGroups = Groups.removeEphemeralGroups(uniqueGroups); @@ -137,7 +138,7 @@ module.exports = function (Groups) { Groups.isMembersOfGroupList = async function (uids, groupListKey) { const results = uids.map(() => false); - let groupNames = await db.getSortedSetRange('group:' + groupListKey + ':members', 0, -1); + let groupNames = await getGroupNames(groupListKey); groupNames = Groups.removeEphemeralGroups(groupNames); if (!groupNames.length) { return results; @@ -153,4 +154,30 @@ module.exports = function (Groups) { }); return results; }; + + async function getGroupNames(keys) { + const isArray = Array.isArray(keys); + keys = isArray ? keys : [keys]; + + const cachedData = {}; + const nonCachedKeys = keys.filter(function (groupName) { + const groupMembers = cache.get('group:' + groupName + ':members'); + const isInCache = groupMembers !== undefined; + if (isInCache) { + cachedData['group:' + groupName + ':members'] = groupMembers; + } + return !isInCache; + }); + + if (!nonCachedKeys.length) { + return isArray ? keys.map(groupName => cachedData['group:' + groupName + ':members']) : cachedData['group:' + keys[0] + ':members']; + } + const groupMembers = await db.getSortedSetsMembers(nonCachedKeys.map(name => 'group:' + name + ':members')); + + nonCachedKeys.forEach(function (groupName, index) { + cachedData['group:' + groupName + ':members'] = groupMembers[index]; + cache.set('group:' + groupName + ':members', groupMembers[index]); + }); + return isArray ? keys.map(groupName => cachedData['group:' + groupName + ':members']) : cachedData['group:' + keys[0] + ':members']; + } };