1

I am using migrate-mongo for managing my database migration and I am trying to create a new migration that create a collection with a validator and insert values in it. I want to use a UUID for the _id property and I am using the uuid-mongodb library to generate it. My problem is that I am not able to set the bsonType of my _id in the validator without causing the data insertion failure. Is there any way to make sure that the id of the documents inserted in the collection is a UUID? I know that mongoose could help me to solve this issue, but I would like the validation to be done at the database level. Also, when I do not specify the _id's bsonType in the validator, the insertion works, it fails validation only when I specify it.

Here is my migration code

const MUUID = require("uuid-mongodb");

module.exports = {
  async up(db) {

    //Will use https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

    await db.createCollection("itemCategories", {
      validator: {
        $jsonSchema: {
          required: ["name"],
          bsonType: "object",
          properties: {
            _id: {"object"}, //I also tried with binData
            name: {
              bsonType: "string",
              maxLength: 50,
            },
            path: {
              bsonType: ["string", "null"],
              pattern: "^,([^,]+,)+$"
            }
          },
          additionalProperties: false,
        }
      },
    });
    await db.collection("itemCategories").createIndex({"name": 1}, {unique: true});
    await db.collection("itemCategories").insertMany([
      {_id: MUUID.v4(), name: "Sport", path: null},
      {_id: MUUID.v4(), name: "Tool", path: null},
      {_id: MUUID.v4(), name: "Entertainment", path: null}
    ]);
  },

  async down(db) {
    await db.dropCollection("itemCategories");
  }
};

And here is the error I get when running it

ERROR: Could not migrate up 20210627041314-create-categories.js: Document failed validation BulkWriteError: Document failed validation
    at OrderedBulkOperation.handleWriteError (C:\Users\username\projectDirectory\node_modules\mongodb\lib\bulk\common.js:1352:9)
    at resultHandler (C:\Users\username\projectDirectory\node_modules\mongodb\lib\bulk\common.js:579:23)
    at handler (C:\Users\username\projectDirectory\node_modules\mongodb\lib\core\sdam\topology.js:943:24)
    at C:\Users\username\projectDirectory\node_modules\mongodb\lib\cmap\connection_pool.js:350:13
    at handleOperationResult (C:\Users\username\projectDirectory\node_modules\mongodb\lib\core\sdam\server.js:558:5)
    at MessageStream.messageHandler (C:\Users\username\projectDirectory\node_modules\mongodb\lib\cmap\connection.js:281:5)
    at MessageStream.emit (events.js:321:20)
    at processIncomingData (C:\Users\username\projectDirectory\node_modules\mongodb\lib\cmap\message_stream.js:144:12)
    at MessageStream._write (C:\Users\username\projectDirectory\node_modules\mongodb\lib\cmap\message_stream.js:42:5)
    at doWrite (_stream_writable.js:441:12)
Vico
  • 308
  • 2
  • 7
  • Look into schema validation. – D. SM Jun 30 '21 at 02:19
  • I'm aware that the problem probably comes from my validator and more specifically from the bsonType I'm giving to the id. However, I can't find the type that would let the value be inserted – Vico Jun 30 '21 at 17:43
  • https://docs.mongodb.com/manual/core/schema-validation/ – D. SM Jun 30 '21 at 22:12
  • Thank you for trying to help, but I can't find anywhere in the documentation an explanation on how to validate an UUID inserted as a Binary object – Vico Jul 02 '21 at 01:02
  • UUID is a subtype of Binary. You can add a requirement that the data you provided was a UUID. If you are thinking of validating the individual bytes, the question doesn't make sense because any sequence of 128 bits is a valid uuid. – D. SM Jul 02 '21 at 18:48
  • Thank you for your answer, could you please tell me how I can add this requirement? That's exactly what I'm trying to do – Vico Jul 02 '21 at 19:15
  • Maybe this is not supported. – D. SM Jul 03 '21 at 00:37

1 Answers1

0

Assuming collection name user_demo and having 2 fields only ( _id, name )

Create collection Schema Validator

db.createCollection("user_demo", {
   validator: {
      $jsonSchema: {
         bsonType: "object",
         title: "User Object Validation",
         required: [ "_id","name"],
         properties: {
            _id: {
               bsonType: "binData",
               description: "Unique identifier,I am using it instead of objectId for portibility",
               pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            },
            name: {
               bsonType: "string",
               description: "'name' must be a string and is required",
               maxLength: 50,
               minLength: 1
            }
         }
      }
   }
} )

Insert data in collection

a) If you already have a uuid4

db.user_demo.insertOne({_id: UUID("a5750db3-1616-45a4-bf92-6a44c3e67342"), name:"shiva"})

b) If you want random uuid4

db.user_demo.insertOne({_id: UUID(), name:"explore"})

Tested with mongo version 6.0.3

Yogesh Yadav
  • 4,557
  • 6
  • 34
  • 40