کار با «اعتبار سنجی ساختار» در عمل

Working with Structure Validation in Practice

19 بهمن 1400
درسنامه درس 24 از سری دوره جامع آموزش MongoDB
MongoDB: کار با «اعتبار سنجی ساختار» در عمل (قسمت 24)

در قسمت قبل با مفهوم کلی schema validation آشنا شدیم و حالا وقت آن است که به صورت عملی شروع به کدنویسی کنیم. ما در همان جلسه کالکشن posts خود را حذف کردیم تا از اول شروع کنیم و برایش schema validation بسازیم اما قبل از شروع کد نویسی دوست دارم نگاهی به کد های قبلی posts بیندازیم (قبل از آنکه حذف شود):

        "_id" : ObjectId("5e8977fcc067c6acacfda166"),
        "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" : ObjectId("5e897545c067c6acacfda164")
                }
        ]
} 

همچنین در جلسه قبل من کد نمونه ای را برایتان قرار دادم:

db.createCollection("posts", {validator: {$jsonSchema: {bsonType: "object", required: ["title", "text", "creator", "comments"]}}})

این فقط قسمتی از کد ما است و نوشتن تمام آن در یک خط بسیار آزار دهنده است. من برای حل این مشکل از VSCode (یا هر ویرایشگری که خودتان می خواهید) استفاده می کنم و کد ها را در خطوط جداگانه می نویسم تا برای شما راحت تر باشد. همچنین به نظر من بهتر است تمام کد ها را یکجا برایتان قرار بدهم و سپس خط به خط آن را توضیح بدهم تا متوجه روند کار بشوید:

db.createCollection('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'
              }
            }
          }
        }
      }
    }
  }
});

اولین آرگومان پاس داده شده به createCollection یک رشته به نام posts است که نام collection ما را مشخص می کند. آرگومان دوم یک شیء یا document دیگر به نام validator است. validator خودش یک document دیگر می گیرد که schema در آن تعریف می شود. انواع validator های مختلف را می توان به عنوان آرگومان به validator پاس داد ولی شدیدا پیشنهاد می شود فقط از jsonSchema$ استفاده کنید (این jsonSchema یک روش خاص برای validate کردن (اعتبارسنجی) است که ما در طول دوره از آن استفاده می کنیم).

در مرحله بعد bsonType را روی object گذاشته ایم. یعنی هر چیزی که به این collection اضافه می شود باید یک document یا شیء معتبر باشد. مرحله بعد تعریف required است که یک آرایه می باشد. required می گوید کدام فیلد ها حتما باید وجود داشته باشند که ما title' و  'text', 'creator'و  'commentsها را اجباری کرده ایم. یعنی اگر در آینده داده ای اضافه شود که یکی از این فیلد ها را نداشته باشد، خطا می گیریم. تا این قسمت خصوصیات کلی document را تعریف کرده ایم و حالا باید کمی جزئی تر شویم و هر کدام از property ها یا خصوصیات یا همان فیلد های خودمان را نیز مشخص کنیم.

بر این اساس در ابتدا title را مشخص کرده ام که یکی از فیلد های ما است. bsonType آن را string گذاشته ام که یعنی مقدار موجود در title باید رشته ای باشد. همچنین یک Description را تعریف کرده ایم. Description به معنی توضیحات است و باید در آن توضیح مختصری در مورد فیلد خودمان بدهیم تا بعدا اگر خطایی گرفتیم بدانیم مشکل از کجاست.  در نهایت این کار را برای text هم انجام می دهیم (هر دو رشته هستند).

اگر یادتان باشد creator همان نویسنده پست بود و ما از reference ها برای آن استفاده کرده بودیم بنابراین نوع آن ObjectId است. اگر شما می خواهید به جای id_ از یک مقدار دیگر استفاده کنید یا اصلا id_ را خودتان تعریف کنید، دیگر ObjectId نخواهد بود (مثلا در id های تعریفی خودتان، string می شود). Description را هم طبق سلیقه خودمان می نویسیم.

برای comments باید نوع array یا آرایه را مشخص کنیم. البته منظور از «باید» این است که من دوست دارم این کار را انجام بدهم. اگر شما می خواهید از انواع داده دیگر (مثلا اشیاء) استفاده کنید، کاملا مختار هستید. سپس items را درون comments گذاشته ایم که مشخص می کند هر کدام از آیتم ها یا همان اعضای درون آرایه چه نوعی داشته باشند. من گفته ام که حتما باید object یا شیء باشد و مثلا نمی تواند رشته باشد. همچنین با خصوصیت required گفته ایم که فیلد های text و author اجباری هستند. چرا؟ به دلیل اینکه خصوصیت comments در posts (قبل از آنکه آن را حذف کنیم) به همین شکل بود:

        "comments" : [
                {
                        "text" : "I liked this post!",
                        "author" : ObjectId("5e897545c067c6acacfda164")
                }
        ]

حالا باید مشخص کنیم که مقادیر درون شیء پاس داده شده به comments چطور باشند. یعنی در حال حاضر گفته ایم comments آرایه ای از اشیاء مختلف است و حالا باید بگوییم درون هر شیء (هر عضو) چه چیزی قرار می گیرد. این کار را با خصوصیت property انجام داده ایم و گفته ایم درون هر شیء یک خصوصیت یا فیلد به نام Text داریم که رشته ای است (String). Description نیز مثل قبل سلیقه ای است. خصوصیت بعدی ما نیز author است که ObjectId است و Description را نیز طبق سلیقه خودمان می نویسیم.

شما می توانید کل کد هایی که بالاتر قرار داده ام را کپی کرده و درون ترمینال خود paste کنید. اگر در ویندوز هستید بهتر است از Cmder استفاده کنید تا مشکلی نداشته باشید اما به هر حال اگر نتوانستید این کار را انجام بدهید، کد ها را بدون شکستگی خطوط و مخصوص command prompt هم قرار می دهم:

db.createCollection('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' } } } } } } } });

با اجرای این کد نتیجه زیر را می گیرید:

{ "ok" : 1 }

یعنی همه چیز با موفقیت ثبت شده است. حالا اگر از کد های قبلی خودمان استفاده کرده و یک post اضافه کنیم مشکلی نخواهیم داشت. مثلا:

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: ObjectId("5e897545c067c6acacfda164")}]})

این همان پستی بود که در جلسات قبل تعریف کرده بودیم. حالا سعی می کنم به author به جای ObjectId یک عدد بدهم (مثلا شاید خودمان id_ را تعریف کرده ایم و عدد 12 را برای یکی از نویسنده ها قرار داده ایم):

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}]})

با اجرای این کد، خطای زیر را در ترمینال مشاهده می کنیم:

WriteError({
        "index" : 0,
        "code" : 121,
        "errmsg" : "Document failed validation",
        "op" : {
                "_id" : ObjectId("5e8ad74f380fbffe5f322254"),
                "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
                        }
                ]
        }
})

در کد بالا در قسمت errmsg گفته شده است:

Document failed validation

یعنی اعتبارسنجی موفقیت آمیز نبود. همچنین اگر از دستور find.pretty استفاده کنیم، می بینیم که سند ما اصلا به پایگاه داده اضافه نشده است.

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

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

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