【问题标题】:MongoDB Conditional validation on arrays and embedded documentsMongoDB 对数组和嵌入文档的条件验证
【发布时间】:2017-11-10 21:52:18
【问题描述】:

我的数据库中有许多文档,我正在应用文档验证。所有这些文档都可能具有嵌入的文档。我可以按照 SQL 非 NULL 检查的方式应用简单的验证(这些实际上是强制执行主键约束),但我想做的是对可选数组和嵌入式文档应用某种条件验证。例如,假设我有一个如下所示的文档:

{
  "date": <<insertion date>>,
  "name" : <<the portfolio name>>,
  "assets" : << amount of money we have to trade with>>
}

显然,我可以在此文档上进行验证,以确保日期名称和资产在插入时都存在。但是,假设我正在管理一个股票投资组合,并且该文档可以有未来的更新以显示一系列股票,如下所示:

{
  "date"      : <<insertion date>>,
  "name"      : <<the portfolio name>>,
  "assets"    : << amount of money we have to trade with>>
  "portfolio" : [
                  { "stockName"  : "IBM",
                    "pricePaid"  : 155.39,
                    "sharesHeld" : 100
                  },
                  { "stockName"  : "Microsoft",
                    "pricePaid"  : 57.22,
                    "sharesHeld" : 250
                  }
                ]
}

是否可以对这个子文档数组应用条件验证?投资组合不存在是有效的,但如果它是数组中的每个文档,则必须包含三个字段“stockName”、“pricePaid”和“sharesHeld”。

【问题讨论】:

    标签: mongodb validation


    【解决方案1】:

    MongoShell

    db.createCollection("collectionname",
    {
      validator: {
        $or: [
          {
            "portfolio": {
              $exists: false
            }
          },
          {
            $and: [
              {
                "portfolio": {
                  $exists: true
                }
              },
              {
                "portfolio.stockName": {
                  $type: "string",
                  $exists: true
                }
              },
              {
                "portfolio.pricePaid": {
                  $type: "double",
                  $exists: true
                }
              },
              {
                "portfolio.sharesHeld": {
                  $type: "double",
                  $exists: true
                }
              }
            ]
          }
        ]
      }
    })
    

    通过上述验证,您可以插入带或不带投资组合的文档。

    在shell中执行validator之后,就可以插入下面的数据了

    db.collectionname.insert({
            "_id" : ObjectId("58061aac8812662c9ae1b479"),
            "date" : ISODate("2016-10-18T12:50:52.372Z"),
            "name" : "B",
            "assets" : 200
    })
    
    
    db.collectionname.insert({
            "_id" : ObjectId("58061ab48812662c9ae1b47a"),
            "date" : ISODate("2016-10-18T12:51:00.747Z"),
            "name" : "A",
            "assets" : 100,
            "portfolio" : [
                    {
                            "stockName" : "Microsoft",
                            "pricePaid" : 57.22,
                            "sharesHeld" : 250
                    }
            ]
    })
    
    
    If we try to insert a document like this 
    
    db.collectionname.insert({
      "date"      : new Date(),
      "name"      : "A",
      "assets"    : 100,
      "portfolio" : [
                      { "stockName"  : "IBM",
    
                        "sharesHeld" : 100
                      }
                    ]
    })
    
    then we will get the below error message
    WriteResult({
            "nInserted" : 0,
            "writeError" : {
                    "code" : 121,
                    "errmsg" : "Document failed validation"
            }
    })
    

    使用猫鼬

    可以,根据您的场景,您可能需要初始化父架构和子架构。

    下面显示的是 mongoose 中的子(组合)模式示例。

    var mongoose = require('mongoose');
    var Schema = mongoose.Schema;
    
    var portfolioSchema = new Schema({
        "stockName" : { type : String, required : true },
        "pricePaid" : { type : Number, required : true },
        "sharesHeld" : { type : Number, required : true },
    }
    

    参考资料:

    http://mongoosejs.com/docs/guide.html

    http://mongoosejs.com/docs/subdocs.html

    Can I require an attribute to be set in a mongodb collection? (not null)

    希望对你有帮助!

    【讨论】:

    • 我不确定我是否理解您的评论,因为我直接使用 MongoDB 而不是 Mongoose(尽管我承认我不知道 Mongoose 是什么)。我希望设置 mongo 数据库,以便验证插入到集合中的所有文档。就我而言,我需要确保对我无法控制插入文档的人的文档执行此操作。
    • @RichardB - 请查看更新后的答案,我已经为您的场景提供了 mongo shell 验证。
    • 感谢克莱门特。当你这样表达时,它看起来很明显,我不明白为什么我没有弄清楚:)
    • 建议的第一个验证器将仅验证数组中的第一项。数组类型最好使用 JSONSchema json-schema.org/understanding-json-schema/reference/array.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    相关资源
    最近更新 更多