ما در قسمت قبل موفق شدیم که داده های location (مکان) کاربر را به داده های آماده geoJSON تبدیل کنیم. در این قسمت می خواهیم فیلد dob را گرفته و مقادیر درون آن را به صورت فیلد های اصلی در سند نمایش بدهیم. در حال حاضر فیلد dob (مخفف date of birth - تاریخ تولد) در کالکشن اصلی به شکل زیر است:
"dob" : { "date" : "1988-10-17T03:45:04Z", "age" : 29 },
من می خواهم فیلد های date و age از درون dob بیرون بیایند و هر کدام تبدیل به فیلد مستقیم خود بشود. انجام این کار ساده است:
db.persons.aggregate([ { $project: { _id: 0, name: 1, email: 1, birthdate: { $convert: { input: "$dob.date", to: "date" } }, age: "$dob.age", location: { type: "point", coordinates: [ { $convert: { input: "$location.coordinates.longitude", to: "double", onError: 0.0, onNull: 0.0 } }, { $convert: { input: "$location.coordinates.latitude", to: "double", onError: 0.0, onNull: 0.0 } } ] } } }, { $project: { gender: 1, email: 1, location: 1, age: 1, birthdate: 1, fullName: { $concat: [{ $toUpper: { $substrCP: ["$name.first", 0, 1] } }, { $substrCP: ["$name.first", 1, { $subtract: [{ $strLenCP: "$name.first" }, 1] }] }, " ", { $toUpper: { $substrCP: ["$name.last", 0, 1] } }, { $substrCP: ["$name.last", 1, { $subtract: [{ $strLenCP: "$name.last" }, 1] }] }] } } }]).pretty()
من دو فیلد جدید به نام های birthdate (تاریخ تولد) و age (سن) را به stage اول داده ام. فیلد age که بسیار ساده است و نیازی به توضیح ندارد اما برای فیلد birthdate دوباره از convert$ استفاده کرده ایم چرا که این فیلد رشته ای است اما ما می خواهیم آن را به صورت عددی داشته باشیم. این رشته با ساختار خاص و استانداردی ذخیره شده است بنابراین می توانیم آن را بدون هیچ زحمت اضافه ای به نوع داده date تبدیل کنیم. اگر دوست دارید در مورد انواع داده های موجود برای convert$ مطالعه کنید، باید به صفحه زیر بروید:
https://docs.mongodb.com/manual/reference/operator/aggregation/convert/
من برخی از این فیلد ها را برایتان لیست می کنم:
در مورد انواع اعداد و مسائل مربوط به آن ها در فصل های آینده صحبت خواهیم کرد. مثلا قبلا به شما گفته بودم که ما در shell کار می کنیم که به صورت پیش فرض تمام اعداد را به صورت اعداد double (اعشاری) 64 بیتی می بیند، در صورتی که این مسئله در Driver های مختلف کاملا متفاوت است و باید به documentation مربوط به Driver خودتان مراجعه کنید. این ها همه مسائلی جزئی هستند که فعلا جای بحث آن ها نیست و باید به فصل مربوطه خودشان تبدیل شوند.
در مرحله آخر نیز حتما باید این فیلد های جدید را به stage بعدی پاس می دادیم و گرنه age و birthdate در همان stage اول دفن شده و از بین می رفتند. پس از اجرای کوئری بالا مجموعه ای از کاربران را دریافت می کنیم که همگی ساختاری مشابه با ساختار مورد نظر ما را دارند. من یکی از این کاربران را می آورم:
"location" : { "type" : "point", "coordinates" : [ 148.0944, 35.5726 ] }, "email" : "louise.graham@example.com", "birthdate" : ISODate("1971-01-21T20:36:16Z"), "age" : 47, "fullName" : "Louise Graham"
همانطور که می بینید birthdate یک فیلد جدید است که فرمت ISODate را دارد و age نیز به صورت عددی نمایش داده شده است.
نکته بعدی در مورد اپراتور های میانبر است! در MongoDB برای تبدیل داده ها به هم (زمانی که نمی خواهیم از onError و onNull استفاده کنیم) فقط دو فیلد input و to را خواهیم داشت به همین دلیل MongoDB اپراتور های میانبری را ارائه داده است تا کار شما را آسان تر کند. برخی از این اپراتور ها عبارت اند از: toString و toLower و toDouble و toInt و الی آخر. از طرفی ما می دانیم که در stage اول خود چنین کدی را داریم:
{ $project: { _id: 0, name: 1, email: 1, birthdate: { $convert: { input: "$dob.date", to: "date" } }, age: "$dob.age", location: { type: "point", coordinates: [ { $convert: { input: "$location.coordinates.longitude", to: "double", onError: 0.0, onNull: 0.0 } }, { $convert: { input: "$location.coordinates.latitude", to: "double", onError: 0.0, onNull: 0.0 } } ] } } },
در این کد، فیلد birthdate فقط input و to را دارد بنابراین می تواند از اپراتور های خلاصه استفاده کند:
{ $project: { _id: 0, name: 1, email: 1, birthdate: { $toDate: "$dob.date" }, age: "$dob.age", location: { type: "point", coordinates: [ { $convert: { input: "$location.coordinates.longitude", to: "double", onError: 0.0, onNull: 0.0 } }, { $convert: { input: "$location.coordinates.latitude", to: "double", onError: 0.0, onNull: 0.0 } } ] } } },
همانطور که می بینید فقط با آوردن toDate$، فیلد dob.date را به نوع date تبدیل کرده ایم. اگر کوئری خود را به شکل بالا اجرا کنیم، کاربران را بدون خطا و مثل همیشه دریافت می کنیم:
"location" : { "type" : "point", "coordinates" : [ 174.2405, 3.6559 ] }, "email" : "anaëlle.adam@example.com", "birthdate" : ISODate("1987-10-20T11:33:44Z"), "age" : 30, "fullName" : "Anaëlle Adam"
اگر شما هم کد ها را به صورت صحیح نوشته باشید نباید به هیچ خطایی برخورد کنید. پیشنهاد من این است که به جای کپی کردن کد ها از این صفحه، سعی کنید خودتان آن ها را بنویسید تا بهتر در ذهنتان بمانند. البته یادتان باشد که هر کدام از این اپراتور های میانبر در ارتباط با داده های مختلف، رفتار متفاوتی نشان می دهد. مثلا toDouble در برخورد با داده های Boolean به شکل زیر عمل می کند:
برای مشاهده اطلاعات بیشتر به documentation رسمی MongoDB به آدرس زیر مراجعه کنید:
https://docs.mongodb.com/manual/reference/operator/aggregation/toDouble/
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.