mongoose - 有可选的附加隐式字段

Posted

技术标签:

【中文标题】mongoose - 有可选的附加隐式字段【英文标题】:mongoose - have optional additional implicit fields 【发布时间】:2015-10-29 10:50:15 【问题描述】:

我有一个包含可以存储任何内容的字段的架构:new Schema(settings : )

我有一个数据库 我想保留这种添加数据而不添加新字段的能力,但是对于某些字段,如果它们不存在,则它们具有默认值。

我可以做到以下几点:

new Schema(
   settings : 
       key :  type : String, default: "abc" 
       // I want to be able to add data that contains more than just "key"
   
);

我只是想确保在从该架构请求数据时,我仍将获得 所有 数据,而不仅仅是明确定义的键?

它似乎有效,但我想确保我仍然可以:

读取所有数据

仍然写入任意数据(即不一定在架构中定义)

是否有关于 mongo/mongoose 的规则会阻止我做这两件事中的一件(我对写作部分非常不确定)?如果有这样的“功能”,怎么办?

注意:我看到了this question。如果我错了,请纠正我,但这些字段不是隐式的(就像 的第一种情况一样),必须定义(实际上是相反的问题)。

编辑:我现在还看到了this question,它解决了我的顾虑(即使接受的解决方案听起来更像是一种解决方法)。但在我的情况下,我已经存储了数据,因此(1 - 禁用严格)意味着编写大量验证代码以确保安全(因为有很多密钥,这是应用程序的最大集合),以及(2 - 混合模式) 将需要迁移此特定子元素的数据...简而言之:我仍然欢迎解决我的特定问题。

【问题讨论】:

禁用strict 是一个选项吗? @robertklep 原样(这个集合是我们数据库的中心点),它会有非常风险(这个集合有很多fields.subfields,并且是链接到几乎所有其他集合)。 【参考方案1】:

我认为您会希望在这里构建自己的自定义验证,而不是依赖默认模式类型验证方法。幸运的是,猫鼬为此提供了便利:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/test');

var testSchema = new Schema(
  settings: 
);

var Test = mongoose.model( 'Test', testSchema, "test" );

testSchema.path('settings').validate(function(value) 
  return Object.keys(value).indexOf("key") != -1;
,'Error "settings" must contain "key" as "settings.key"');


//var test = new Test( settings:  "key": "something"  );
var test = new Test( settings:   );

test.save(function(err) 
  try 
    if (err) throw err;
    console.log(test);
   catch (e) 
    console.log(e);
  
);

所以基本上,我已经为模式中的“设置”路径设置了验证函数,以查找带有它自己的对象的“键”的存在。如果该“key”不存在,则会在错误中报告异常。

与任何此类错误一样,当您.save() 对象时,它将在err 对象中返回,从而阻止写入。然后可以根据您的需要对其进行操作以处理错误,并报告定义的消息。

所以这是一个自包含的“测试”,您可以交替取消注释对象的有效数据并成功保存该对象而不会报告错误。


或者你可以做一个“预保存”来填写一些默认数据:

testSchema.pre("save",function(next) 
  this.settings = (this.settings) ? this.settings : ;
  if (Object.keys(this.settings).indexOf("key") == -1)
    this.setting.key = "abc";
  next();
);

如果它不存在,则填充默认值。

【讨论】:

我可以使用 validate 函数为该特定子字段 (settings.subfield) 插入默认值吗? @nha 一个“pre”保存钩子对于默认数据或一般操作会更好。这实际上会在验证后触发。还有一个“pre”验证钩子你也可以使用,并不是说我认为如果你在钩子中设置它那么数据应该是有效的。 那么这个pre-save hook或许可以解决我的问题,谢谢 等等,抱歉,它实际上不适用于预保存挂钩。因为我已经有现有数据,所以我需要更像预取钩子的东西。 @nha 我只是在回答您提出的问题,即仅验证某个密钥并忽略其他密钥。我也很好地给出了一个“预保存”示例,并对我的答案进行了额外的编辑。如果这导致您提出其他问题,那么Post another question 或几个。【参考方案2】:

尝试这样使用

new Schema(
    settings : 
);

var modelObj = new myModel();
modelObj.settings.key = "keyval";
modelObj.settings.key1 = "keyval";
modelObj.settings.key2 = "keyval";
modelObj.settings.key3 = "keyval";
modelObj.save(function(err)
    //handle
);

【讨论】:

以上是关于mongoose - 有可选的附加隐式字段的主要内容,如果未能解决你的问题,请参考以下文章

angularjs 路由可以有可选的参数值吗?

你可以在 Typescript 函数中有可选的解构参数吗?

为啥 Swift 隐式展开可选的“nil”?

MYSQL创建表的约束条件(可选)

Swift:如果变量 a 是非可选的,那么为啥变量 b 是可选的? [复制]

对如何使 Django 模型字段可选的感到困惑