MongoDB对数组和嵌入文档的条件验证

时间:2016-10-18 10:37:04

标签: mongodb validation

我的数据库中有许多文档,我正在应用文档验证。所有这些文件都可能包含嵌入的文件。我可以沿着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”,那么它对于投资组合是有效的。但

1 个答案:

答案 0 :(得分:2)

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中执行验证器后,您可以插入以下数据

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

是的,可以完成,根据您的方案,您可能需要初始化父模式和子模式。

下面显示的是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)

希望它有帮助!