[似乎无法弄清楚为什么我的数据库更新/更新操作的json验证在Node服务器应用程序中和直接在MongoDB Shell中都一直失败。我可能会丢失一些东西,但不知道可能是什么。
我正在使用MongoDB Atlas。目前,只有删除db.createCollection验证器选项参数后,更新才能成功。
但是模式验证对于此用例至关重要。
ERROR :::: MongoError: Document failed validation
at MessageStream.messageHandler (..\node_modules\mongodb\lib\cmap\connection.js:261:20)
at MessageStream.emit (events.js:209:13)
at MessageStream.EventEmitter.emit (domain.js:476:20)
at processIncomingData (..\node_modules\mongodb\lib\cmap\message_stream.js:144:12)
at MessageStream._write (..\node_modules\mongodb\lib\cmap\message_stream.js:42:5)
at doWrite (_stream_writable.js:428:12)
at writeOrBuffer (_stream_writable.js:412:5)
at MessageStream.Writable.write (_stream_writable.js:302:11)
at TLSSocket.ondata (_stream_readable.js:722:22)
at TLSSocket.emit (events.js:209:13)
at TLSSocket.EventEmitter.emit (domain.js:476:20)
at addChunk (_stream_readable.js:305:12)
at readableAddChunk (_stream_readable.js:286:11)
at TLSSocket.Readable.push (_stream_readable.js:220:10) at TLSWrap.onStreamRead (internal/stream_base_commons.js:166:17) {
operationTime: Timestamp { _bsontype: 'Timestamp', low_:
4, high_: 1591981465 },
ok: 0,
code: 121,
codeName: 'DocumentValidationFailure',
'$clusterTime': {
clusterTime: Timestamp { _bsontype: 'Timestamp', low_:
4, high_: 1591981465 },
signature: { hash: [Binary], keyId: [Long] }
},
name: 'MongoError'
}
代码:
const email = Object.freeze([{
value: 'p',
status: 'active'
}, {
value: 'b',
status: 'defunct'
}, {
value: 'o'
status: 'active'
}, {
value: 'w'
status: 'inactive'
}]);
const schema = Object.freeze({
additionalProperties: false,
bsonType: 'object',
description: 'email data point',
properties: {
_id: {
bsonType: 'objectId'
},
address: {
bsonType: 'string',
maxLength: 64,
pattern: '^\w+@\w+(.\w+)+$',
description: 'required: email address'
},
contactTypes: {
bsonType: 'array',
description: 'required: a set of unique string values',
items: {
bsonType: 'string',
enum: email.map( e => e.value )
},
uniqueItems: true
},
dateCreated: {
bsonType: 'long',
description: 'required: contact email creation timestamp in ms since epoch'
},
isPrimary: {
bsonType: 'bool'
},
lastUpdated: {
bsonType: 'long',
description: 'contact email recent update timestamp in ms since epoch'
}
},
required: [ 'address', 'contactTypes', 'dateCreated', 'isPrimary' ]
});
// db connection logic
const colName = 'emails';
db.createCollection( colName, {
validator: {
$jsonSchema: { ...schema }
}
});
const doc = {
address: '[email protected]',
contactTypes: [ 'p', 'b' ],
isPrimary: true,
};
let updated;
( async () => {
try {
updated = await db.collection( colName ).findOneAndUpdate( doc, {
$set: {
...doc,
dateCreated: Date.now()
}
}, {
returnNewDocument: true,
upsert: true
});
} catch( e ) {
console.error( e.message );
}
})();
使用Mongo Shell的相同请求:
MongoDB Enterprise D0-shard-0:PRIMARY> db.emails.findOneAndUpdate({
address: '[email protected]',
contactTypes: [ 'p', 'b' ],
isPrimary: true
}, {
$set: {
address: '[email protected]',
contactTypes: [ 'p', 'b' ],
isPrimary: true,
dateCreated: 1591981465
}
}, {
returnNewDocument: true,
upsert: true
})
结果:
2020-06-12T12:33:47.785-0700 E QUERY [js] uncaught exception: Error: findAndModifyFailed failed: {
"operationTime" : Timestamp(1591990428, 24),
"ok" : 0,
"errmsg" : "Document failed validation",
"code" : 121,
"codeName" : "DocumentValidationFailure",
"$clusterTime" : {
"clusterTime" : Timestamp(1591990428, 24),
"signature" : {
"hash" : BinData(0,"9QzeeWQw4kYtnf1m/2dTyvNphAQ="),
"keyId" : NumberLong("6798592801870184449")
}
}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DBCollection.prototype.findAndModify@src/mongo/shell/collection.js:725:15
DBCollection.prototype.findOneAndUpdate@src/mongo/shell/crud_api.js:900:12
@(shell):1:1
bsonType: 'int'
是32位整数。这不足以容纳自纪元以来的毫秒数。
您应该使用bsonType: 'long'
。
编辑
在示例文档中,dateCreated: 1591981465
创建的日期是int
,而不是long
,因此不会匹配。
如果要同时允许两种类型,请使用type: "number"
代替bsonType: "long"
Javascript使用反斜杠转义字符串值。为了在字符串中获得文字反斜杠,您需要将其加倍,例如:
模式:'^ \\ w + @ \\ w +(。\\ w +)+ $'