Mongoose Schema验证XOR字段

时间:2015-05-19 19:44:18

标签: node.js mongodb mongoose

我有以下mongoose架构

var Mongoose = require("mongoose");
var Schema = Mongoose.Schema;

var headerSchema = new Schema({
    lang : {
        type: String,
        required: true,
        match: [ /^(en|es|pt)$/, "{VALUE} is not a supported language" ],
        index: { unique: true }
    },
    menu : {
        type: [{
            link: { type: Schema.ObjectId, ref: "Link"},
            dropdown: { type: Schema.ObjectId, ref: "Dropdown"},
            autopopulate: true
        }]
    }
});

headerSchema.plugin(require("mongoose-autopopulate"));

module.exports = Mongoose.model("header", headerSchema);

正如您可能已经猜到的,这描述了网页标题的配置文档。此标头具有导航(架构中的菜单),其中每个项目可以是下拉列表或链接,但不能同时是两者。有没有办法在我的架构中添加自定义验证,只允许保存文档,如果设置了其中任何一个,但不是两者都有,而不是两者都没有? (想想布尔运算XOR)

例如,这是一个有效的标题文档:

{
  lang: "es",
  menu: [{
    link: {
      title: "Contact",
      href: "/contact"
    }
  }, {
    dropdown: {
     title: "FAQ",
     links: [{
       title: "What is this?",
       href : "/about"
     }]
    }
  }]
}

1 个答案:

答案 0 :(得分:0)

这似乎有效:

menu : {
    type: [{
        type: Schema.Types.Mixed,
        required: true,
        validate: [ isDropdownOrLink, "{VALUE} is neither a dropdown nor a link" ]
    }]
}

function isDropdownOrLink (value) {
    if (!value) {
        return false;
    }

    return value instanceof Link || value instanceof Dropdown;
}

还使用Schema.Types.Mixed简化了我的架构。我现在暂时打开这个问题,因为我的回答稍微改变了原来的问题(因为我已经改变了架构)