I am currently trying to setup a schema for custom Discord guild commands:
const GuildCommandsSchema = new mongoose.Schema({
_id: String,
commands: [
{
name: {
type: String,
unique: true,
required: true,
},
action: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
},
],
});
Is this ok, performancewise, or could I improve it? I feel like Mongo would need to look through all commands, since it can't index any commands inside 'commands' even though 'name' is unique.
If that's fine, how can I access the values inside commands? I would need to find the right command via 'name' if it exists, otherwise create it and add/update 'action' 'author'.
I tried something like this:
const updatedCommand = await GuildCommands.findOneAndUpdate(
{ _id },
{
$set: {
[`commands.$[outer].name`]: name,
[`commands.$[outer].action`]: action,
[`commands.$[outer].author`]: author,
},
},
{
arrayFilters: [{ 'outer.name': name }],
}
);
Unfortunately that does not create commands if they don't exist.
Thanks for your help
CodePudding user response:
aggregate
db.collection.update({},
{
$set: {
"commands.$[c].name": "1",
"commands.$[c].author": "1",
"commands.$[c].action": "1"
}
},
{
arrayFilters: [
{
"c.author": "34"
}
],
multi: true
})
CodePudding user response:
To answer my own question:
I changed my Schema to use Maps instead of Arrays for performance improvments and also better model management.
const GuildCommandsSchema = new mongoose.Schema(
{
_id: String,
commands: {
type: Map,
of: {
_id: false,
name: {
type: String,
required: true,
},
action: {
type: String,
required: true,
},
active: {
type: Boolean,
required: true,
default: true,
},
author: {
type: String,
required: true,
},
},
},
},
{ versionKey: false }
);
The new query to find and update/create a command is also better imo:
const findCommand = await GuildCommands.findOne({ _id });
if (!action) {
const getCommand = findCommand.commands.get(name);
if (getCommand) {
message.reply(getCommand.action);
} else {
message.reply(`Cannot find ${name}`);
}
} else {
findCommand.commands.set(name, {
name,
action,
author,
});
findCommand.save();
}