用NodeJS进行MongoDB更新JsonValidator失败

问题描述 投票:0回答:1

[似乎无法弄清楚为什么我的数据库更新/更新操作的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
node.js mongodb mongodb-atlas json-schema-validator
1个回答
1
投票

bsonType: 'int'是32位整数。这不足以容纳自纪元以来的毫秒数。

您应该使用bsonType: 'long'

编辑

在示例文档中,dateCreated: 1591981465创建的日期是int,而不是long,因此不会匹配。

如果要同时允许两种类型,请使用type: "number"代替bsonType: "long"

Javascript使用反斜杠转义字符串值。为了在字符串中获得文字反斜杠,您需要将其加倍,例如:

模式:'^ \\ w + @ \\ w +(。\\ w +)+ $'

© www.soinside.com 2019 - 2024. All rights reserved.