如果两个字段相等,是否可以防止Mongo创建文档?
例如,这应该被接受:
{ A: 'foo', B: 'bar' }
但这应该被拒绝:
{ A: 'foo', B: 'foo' }
在调用Mongo之前执行检查很简单,但是这样做的目的是防止从shell修改集合后发生错误。
为了清楚起见,我并不是要比较一个文档的字段与另一个文档的字段。文档中的值不能与同一文档中的其他值冲突。
答案 0 :(得分:1)
实际上,做到这一点很容易,尽管有一个警告,但我无法以令人满意的方式解决。
有一个叫做schema validation的东西。我们将使用它,但是我们使用query expression代替了实际的JsonSchema。
> db.runCommand({
// We modify an existing collection named "validate"...
collMod:"validate",
// ...adding a validator...
"validator":{
// ...ensuring that documents are only considered valid if
// the value of field A is not equal the value of field B
$expr:{$ne:["$A","$B"]}}
}
)
{ "ok" : 1 }
让我们对其进行测试:
> db.validate.insert({"A":"foo","B":"bar"})
WriteResult({ "nInserted" : 1 })
> db.validate.insert({"A":"foo","B":"foo"})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
是的,到目前为止看起来还不错,不是吗?除此之外,有一个警告:
> db.validate.insert({"A":"foo","B":"foo "})
WriteResult({ "nInserted" : 1 })
一个简单的空白实际上可以击败我们的一点平等检查。因此,显然我们需要扩展验证器:
db.runCommand({collMod:"validate","validator":{$and:[
// Both A and B must not have leading or trailing white space.
{"A":{$regex:/^\w+$/}},
{"B":{$regex:/^\w+$/}},
// As before.
{$expr:{$ne:["$A","$B"]}}
]}})
所以,让我们重新检查一下:
db.validate.deleteMany({})
{ "acknowledged" : true, "deletedCount" : 2 }
> db.validate.insert({"A":"foo","B":"bar"})
WriteResult({ "nInserted" : 1 })
> db.validate.insert({"A":"foo","B":"bar "})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
> db.validate.insert({"A":"foo","B":"foo"})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
似乎可以正常工作。但是,用户无法找出为什么文档验证失败。如果可以忍受,那么您有解决方案。 就个人而言,我宁愿使用专用的CLI工具进行修改,并事先验证输入。生产数据库的数据修改不应使用DBMS CLI。
此外,还有一些与用例相关的问题:“ foo”是否等于“ Foo”和“ FOO”?如果是这样,当A持有“ fOo”而B持有“ foO”时,A和B是否相等?依此类推。