تغییر تنظیمات schema validation

Change Schema Validation Settings

19 بهمن 1400
درسنامه درس 25 از سری دوره جامع آموزش MongoDB
MongoDB: تغییر تنظیمات schema validation (قسمت 25)

در قسمت قبل یک اعتبار سنجی برای ساختار پایگاه داده خود ساختیم و مشاهده کردیم که با نوشتن مقادیر اشتباه، کوئری ما نادیده گرفته می شود. اگر یادتان باشد، توضیح داده بودم که schema validation به شکل زیر کار می کند.

برای سطح اعتبار سنجی:

  • strict یعنی تمام دستورات insert و update بررسی و اعتبار سنجی شوند.
  • moderate یعنی تمام دستورات insert  برسی می شوند اما دستورات update  فقط برای document هایی بررسی می شود که از قبل معتبر بوده اند. با انتخاب این گزینه، اگر داده های نامعتبری از قبل در پایگاه داده شما وجود داشته باشد (قبل از اینکه اعتبارسنجی را تعریف و اعمال کنید از پایگاه داده استفاده می کردید) به آن ها توجه نخواهد شد، در صورتی که در حالت strict داده هایی که از قبل نامعتبر باشند نیز خطا می گیرند.

برای validation action (پاسخ سرور پس از خطا):

  • اعلام خطا توسط MongoDB (پرتاب error) و نادیده گرفتن کوئری شما (در این حالت دستور شما اجرا نمی شود).
  • اعلام هشدار توسط MongoDB (پرتاب warning) و اجرای کوئری (به شما هشدار داده می شود اما به هر حال دستور را اجرا می کند).

با این حساب می فهمیم که حالت پیش فرض در MongoDB حالت پرتاب error و نادیده گرفتن کوئری است. سوال ما اینجاست که اگر خواستیم آن را تغییر دهیم چه کار باید کرد؟ احتمالا می گویید که باید به همان دستور جلسه قبل چند مورد ساده را اضافه کنیم. حرف شما درست است اما ما در جلسه قبل schema validation خود را تعریف کردیم و حالا نمی خواهم collection را به همراه داده هایش پاک کنم تا دوباره یک collection جدید با یک schema validation جدید بسازم. راه حل چیست؟

متدی به نام runCommand وجود دارد که به شما کمک می کند دستورات مربوط به پایگاه داده را اجرا کنید. دستوراتی مثل aggregate یا find یا delete یا insert و الی آخر. شما می توانید لیستی از تمام دستورات پایگاه داده را در لینک زیر پیدا کنید:

https://docs.mongodb.com/manual/reference/command/

ما می توانیم از متد runCommand برای اجرای دستور خاصی استفاده کرده و validation خود را ویرایش کنیم:

db.runCommand({collMod: "posts", X})

در کد بالا collMod به معنی collection Modifier (ویرایشگر کالکشن) است و همانطور که از نامش پیداست، collection های ما را ویرایش می کند. من در اینجا posts را به آن پاس داده ام که یعنی می خواهم collection ای به نام posts را ویرایش کنم. حالا باید به جای X، مقدار ویرایش شده خود را پاس بدهیم.  در واقع ساختار اصلی استفاده از collMod بدین شکل است:

db.runCommand( { collMod: <collection or view>, <option1>: <value1>, <option2>: <value2> ... } )

هر option یکی از تنظیماتی است که می خواهیم ویرایش کنیم و احتمالا حدس می زنید که گزینه های بسیار زیادی برای ویرایش وجود دارد:

https://docs.mongodb.com/manual/reference/command/collMod/

ما در اینجا می خواهیم روی schema validation تمرکز کنیم بنابراین باید به جای X در دستور بالا validator را قرار بدهیم تا collMod بداند که قصد ویرایش چه چیزی را داریم. مثلا اگر بخواهیم دقیقا اعتبارسنجی جلسه پیش را به آن پاس بدهیم باید از قسمت validator تا آخر آن را به جای X بگذاریم:

  validator: {
    $jsonSchema: {
      bsonType: 'object',
      required: ['title', 'text', 'creator', 'comments'],
      properties: {
        title: {
          bsonType: 'string',
          description: 'must be a string and is required'
        },
        text: {
          bsonType: 'string',
          description: 'must be a string and is required'
        },
        creator: {
          bsonType: 'objectId',
          description: 'must be an objectid and is required'
        },
        comments: {
          bsonType: 'array',
          description: 'must be an array and is required',
          items: {
            bsonType: 'object',
            required: ['text', 'author'],
            properties: {
              text: {
                bsonType: 'string',
                description: 'must be a string and is required'
              },
              author: {
                bsonType: 'objectId',
                description: 'must be an objectid and is required'
              }
            }
          }
        }
      }
    }
  }

بنابراین کد ما به شکل زیر در می آمد:

db.runCommand({collMod: "posts", validator: { $jsonSchema: { bsonType: 'object', required: ['title', 'text', 'creator', 'comments'], properties: { title: { bsonType: 'string', description: 'must be a string and is required' }, text: { bsonType: 'string', description: 'must be a string and is required' }, creator: { bsonType: 'objectId', description: 'must be an objectid and is required' }, comments: { bsonType: 'array', description: 'must be an array and is required', items: { bsonType: 'object', required: ['text', 'author'], properties: { text: { bsonType: 'string', description: 'must be a string and is required' }, author: { bsonType: 'objectId', description: 'must be an objectid and is required' } } } } } } }})

اما ما نمی خواهیم کد جلسه قبل را تکرار کنیم بلکه باید گزینه های دیگری به آن اضافه نماییم. ما می توانیم دو گزینه زیر را به آن اضافه کنیم:

  • validationLevel که یکی از مقادیر off یا strict (حالت پیش فرض) یا moderate را قبول می کند. در مورد این سه حالت قبلا صحبت کرده ایم. Off یعنی اصلا validation نداشته باشیم، strict یعنی همه چیز اعتبارسنجی شود و moderate یعنی document های نامعتبر قبلی را نادیده بگیر اما از این به بعد همه چیز را اعتبار سنجی کن.
  • validationAction که یکی از مقادیر Warn یا error را می گیرد و توضیحات آن را قبلا داده ام.

من فعلا می خواهم validationLevel روی حالت Strict بماند بنابراین مقدار آن را تغییر نمی دهم اما validationAction را به شکل زیر اضافه می کنم. این خصوصیت حتما باید در کنار validator قرار بگیرد (نه داخل آن):

db.runCommand({
  collMod: 'posts',
  validator: {
    $jsonSchema: {
      bsonType: 'object',
      required: ['title', 'text', 'creator', 'comments'],
      properties: {
        title: {
          bsonType: 'string',
          description: 'must be a string and is required'
        },
        text: {
          bsonType: 'string',
          description: 'must be a string and is required'
        },
        creator: {
          bsonType: 'objectId',
          description: 'must be an objectid and is required'
        },
        comments: {
          bsonType: 'array',
          description: 'must be an array and is required',
          items: {
            bsonType: 'object',
            required: ['text', 'author'],
            properties: {
              text: {
                bsonType: 'string',
                description: 'must be a string and is required'
              },
              author: {
                bsonType: 'objectId',
                description: 'must be an objectid and is required'
              }
            }
          }
        }
      }
    }
  },
  validationAction: 'warn'
});

دستور بدون اسپیس و line break برای ترمینال:

db.runCommand({ collMod: 'posts', validator: { $jsonSchema: { bsonType: 'object', required: ['title', 'text', 'creator', 'comments'], properties: { title: { bsonType: 'string', description: 'must be a string and is required' }, text: { bsonType: 'string', description: 'must be a string and is required' }, creator: { bsonType: 'objectId', description: 'must be an objectid and is required' }, comments: { bsonType: 'array', description: 'must be an array and is required', items: { bsonType: 'object', required: ['text', 'author'], properties: { text: { bsonType: 'string', description: 'must be a string and is required' }, author: { bsonType: 'objectId', description: 'must be an objectid and is required' } } } } } } }, validationAction: 'warn' });

اگر می خواستیم مقدار validationLevel را نیز تغییر بدهیم باید چنین کاری انجام می دادیم (به قسمت انتهایی کد توجه کنید):

db.runCommand({ collMod: 'posts', validator: { $jsonSchema: { bsonType: 'object', required: ['title', 'text', 'creator', 'comments'], properties: { title: { bsonType: 'string', description: 'must be a string and is required' }, text: { bsonType: 'string', description: 'must be a string and is required' }, creator: { bsonType: 'objectId', description: 'must be an objectid and is required' }, comments: { bsonType: 'array', description: 'must be an array and is required', items: { bsonType: 'object', required: ['text', 'author'], properties: { text: { bsonType: 'string', description: 'must be a string and is required' }, author: { bsonType: 'objectId', description: 'must be an objectid and is required' } } } } } } }, validationLevel: 'moderate', validationAction: 'warn' });

اما من validatioLevel را حذف می کنم تا روی strict باقی بماند. با اجرای این کد باید نتیجه زیر را بگیرید:

{ "ok" : 1 }

سوال من این است که حالا اگر کد زیر را اجرا کنم چه می شود؟

db.posts.insertOne({title: "My first post!", text: "This is my first post, I hope you like it!", tags: ["new", "tech"], creator: ObjectId("5e897545c067c6acacfda165"), comments: [{text: "I liked this post!", author: 12}]})

اگر یادتان باشد در جلسه قبل این کد نادیده گرفته شد چرا که author از نوع ObjectId نیست بلکه عدد 12 است! در آن جلسه حالت اعتبار سنجی ما روی error بود اما حالا روی Warn هستیم بنابراین با اجرای کد بالا، دستور ما نادیده گرفته نشده و این مقدار در پایگاه داده ثبت می شود! پیام هشدار یا همان warn هم درون فایل log ما روی سیستم نوشته شده است اما فعلا به آن کار نداریم و فایل log را در فصل مخصوص به خودش بررسی خواهیم کرد. در اینجا هیچ گزینه صحیح یا غلطی وجود ندارد و همه چیز بسته به سلیقه شما و نیاز های برنامه تان می باشد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش MongoDB توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

مقالات مرتبط
آخرین سوالات کاربران
5451218 در 4 سال قبل پرسیده:
ما را دنبال کنید
اینستاگرام روکسو تلگرام روکسو ایمیل و خبرنامه روکسو