首页 > 解决方案 > 仅包含与另一条路径的值相关的 Mongoose 模式的路径

问题描述

假设我有一个这样的架构:

Schema({
    username: String,
    privilege: {
        type: String,
        enum: ["admin", "pro", "user", "guest"],
        required: false,
        default: "user"
    },
    tagType: { // A little badge that appears next to users' names on the site.
        ///???
    }
});

对于,如果是tagType,我希望能够定义这样的东西:privilegeadmin

{
    color: String,
    image: String,
    text: {
        type: String,
        required: true,
        enum: ["I'm the highest rank", "I'm an admin", "Admin privileges are great"]
    },
    dateAdded: Date
}

同时,如果privilegepro

{
    color: String,
    text: {
        type: String,
        required: false,
        enum: ["This website is great", "I'm am a Pro user", "I get a nice tag!"],
        default: "This website is great"
    },
    dateAdded: Date
}

同时,对于所有userguest条目,不应允许任何选项。

这种动态交叉检查可能吗?我已经尝试通读文档,但是尽管其中的内容看起来要复杂得多,但我找不到任何方法来实现这一点。

标签: node.jsmongooseschemamongoose-schema

解决方案


您可以通过使用鉴别器来实现这一点

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const userSchema = new Schema(
  {
    username: String,
    privilege: {
      type: String,
      enum: ["admin", "pro", "user", "guest"],
      required: false,
      default: "user"
    }
  },
  { discriminatorKey: "privilege" }
);

const User = mongoose.model("User", userSchema);

User.discriminator(
  "admin",
  new Schema({
    tagType: {
      color: String,
      image: String,
      text: {
        type: String,
        required: true,
        enum: ["I'm the highest rank","I'm an admin","Admin privileges are great"]
      },
      dateAdded: { type: Date, default: Date.now }
    }
  })
);

User.discriminator(
  "pro",
  new Schema({
    tagType: {
      color: String,
      text: {
        type: String,
        required: false,
        enum: ["This website is great","I'm am a Pro user","I get a nice tag!"],
        default: "This website is great"
      },
      dateAdded: { type: Date, default: Date.now }
    }
  })
);

module.exports = User;

使用此模型和架构,您可以使用 tagType 创建用户,它将被忽略。

创建用户的示例代码:

const User = require("../models/user");

router.post("/user", async (req, res) => {
  let result = await User.create(req.body);
  res.send(result);
});

示例请求正文:

{
    "username": "user 1",
    "tagType": {
        "color": "red",
        "text": "I'm an admin"
    }
}

回复:

{
    "privilege": "user",
    "_id": "5dfa07043a20814f80d60d6b",
    "username": "user 1",
    "__v": 0
}

创建管理员的示例请求:(请注意,我们添加了"privilege": "admin"

{
    "username": "admin 1",
    "privilege": "admin",
    "tagType": {
        "color": "red",
        "text": "I'm an admin"
    }
}

响应:(注意 tagType 已保存)

{
    "_id": "5dfa07a63a20814f80d60d6d",
    "privilege": "admin",
    "username": "admin 1",
    "tagType": {
        "color": "red",
        "text": "I'm an admin",
        "dateAdded": "2019-12-18T11:04:06.461Z"
    },
    "__v": 0
}

推荐阅读