猫鼬:无法将数据保存到空对象

时间:2020-07-26 13:09:08

标签: javascript node.js mongoose discord

这是我的情况:

我有一个简单的模式,该模式具有一个称为命令的对象,最初将其设置为{}

commands:{}

当我将文档添加到数据库时,我遍历了一个命令文件,并通过执行command["command"] = "blah blah";将它们添加到了对象中。我这样做的方式如下(我工作的代码很旧):

Guild.findOne({guildId:serverId}).then(x=>{
  x.commands = {};
  for(let command of Object.values(commandInfo)){
    if(!command.name) continue;
    const getSubs = ()=>{
      const subArray = {};
      if(!command.subCommands) return;
      for(let subs of Object.values(command.subCommands)){
        subArray[subs.name] = {
          access:subs.access,
          disabled:subs.disabled
        }
      }
      x.commands[command.name].subCommands = subArray;
    }
    x.commands[command.name] = {
      access:command.access,
      bounded:command.bounded,
      disabled:command.disabled,
    }
    getSubs();
  }
  console.log("Success!");
  x.save();
});

这些命令包含以下内容(我的示例将使用两个命令):

work:{
  access:"All",
  bounded:"A Channel",
  disabled:false
},
profile:{
  access:"All",
  bounded:"Another Channel",
  disabled:false,
  subCommands:{
    bio:{
      access:"All",
      disabled:true
    }
    register:{
      access:"All",
      disabled:false
   }
 }

现在,我制作了一个配置文件,该文件应该可以编辑这些命令。我编写的代码工作得很好。但是,Mongoose无法保存命令的任何更改。除与命令相关的所有内容外,我的架构中的其他所有内容都可以在配置文件中使用。

我知道是什么问题。猫鼬在架构中找不到命令,并且以某种方式感到困惑。而且我知道可以通过将所有命令及其属性添加到Schema中来解决此问题。唯一的问题是它很乏味,而且不是我添加任何新命令的绝对解决方案。另外,我在单独的文件中拥有命令的所有信息,因此我不想重写已经写的内容。

我的问题是:我的问题是否有解决方法?我尝试设置commands to Schema.Types.Mixed,但这并不能解决问题。我也到处搜寻类似的东西,但找不到任何东西。

以下是完整的架构:

const {Schema, model} = require("mongoose");
const settings = require("../utils/settings");

const guildSchema = Schema({
  guildId:String,
  symbols:{
    prefix:{type:String, default:";"},
    currency:{type:String, default:"$"}
  },
  channels:{
    casinoChannels:Array,
    fineChannels:Array
  },
  commands:Schema.Types.Mixed,
  hierarchy:[{
    name:String,
    role:{type:String, default:""},
    members:Array
  }],
  users:[{
    userId:String,
    cash:Number,
    bank:Number,
    items:[{
      name:String, 
      amount:Number
    }],
    timers:{
      work:String,
      crime:String,
      hack:String,
      steal:String,
      daily:String,
      weekly:String,
      marry:String,
      divorce:String,
      idea:String,
      report:String,
      quiz:String
    },
    fine:{
      fineId:String,
      description:String,
      report:String,
      pay:Number
    },
    used:String
  }],
});

guildSchema.virtual("addUser").set(function(id){
  const user = {
    userId:id,
    cash:settings.cash,
    bank:settings.bank
  };

  this.users.push(user);
  return user;
});   

module.exports = model("Servers", guildSchema);

2 个答案:

答案 0 :(得分:0)

使用findOneAndUpdate更新集合中的现有文档。

在mongodb的“命令”中将要更新的对象放在x变量中。

Guild.findOneAndUpdate({guildId : serverId},{commands : x));

找到匹配项后,将使用此新数据直接更新/替换存储在x变量中的对象。

更新为不完全替换现有对象

let guild = Guild.findOne({guildId : serverId});
if(guild){
// guild.commands here will have the existing object. 
// Modify it as required and then use findOneAndUpdate again
}

答案 1 :(得分:0)

解决方案非常简单。我从以下网站上获取的:https://mongoosejs.com/docs/2.7.x/docs/schematypes.html

致谢:

由于它是一种无模式类型,因此您可以将其值更改为其他任何值,但是Mongoose失去了自动检测/保存的功能 这些变化。要“告诉”猫鼬混合类型的值具有 更改后,调用传递的文档的.markModified(path)方法 您刚刚更改的混合类型的路径。

因此,每当我更新命令时(也就是每当我更改访问权限,有界变量或禁用变量时),我都会在命令功能上使用标记修改方法。我的代码是:

guildSchema.virtual("saveCommands").set(function(name){
  if(["access", "bounded", "disabled"].includes(name)) this.markModified('commands');
});