چرا سکان آکادمی؟
بررسی ماژول Mapping و انواع روش‌های کار با آن

بررسی ماژول Mapping و انواع روش‌های کار با آن

در قسمت قبلی با ساختار کلی index در Elasticsearch آشنا شدیم. اکنون می‌خواهیم جزییات ماژول mapping (mapper) را بررسی کنیم. این ماژول تعیین می‌کند هر document و فیلد‌های آن چگونه ذخیره و ایندکس شوند! دقت کنید در این تعریف مفهوم ذخیره شدن (store) و ایندکس شدن (index) متفاوت از یکدیگر در نظر گرفته شده است. این به دلیل آن است که در کنار source_ داده‌ای که در Elasticsearch ذخیره می‌شود، term های استخراج شده از داده‌ها نیز در inverted index ثبت می‌شوند و دقیقا آن چه که در فرایند جستجو اهمیت دارد، term هایی از فیلد‌های document است که ایندکس شده باشند! بنابراین کیفیت کوئری‌های جستجو تا حد زیادی به نوع ایندکس شدن داده‌ها وابسته است و اصلی‌ترین جایی که تعیین می‌کنیم داده‌ها چگونه ایندکس شوند، همین ماژول mapping است.

قبل از ادامه‌ی این قسمت، مجدد یادآوری کنم که برای ساخت یک index از API ایجاد آن به شکل زیر می‌توانیم استفاده کنیم:

PUT <index-name>
{
	"settings": {
		...
	},
	"mappings": {
		...
	}
}

که <index-name> نام دلخواه برای index و کلید‌های settings و mappings ماژول‌ها و تنظیمات index را مشخص می‌کنند.

در Elasticsearch می‌توان mapping را به صورت dynamic (پویا) و یا explicit (صریح) تعیین کرد. شیوه‌ی dynamic همان روشی است که Elasticsearch به کاربر اجازه می‌دهد تا صرفا داده‌هایش را ایندکس کند و در مورد میزان مصرف منابع، بهینه بودن جستجو یا کیفیت نتایج آن دغدغه‌ی چندانی نداشته باشد. این روش برای شروع کار با Elasticsearch خیلی مناسب است.

اما اگر آگاهی خوبی از ساختار داده‌ها داشته باشیم و بخواهیم کنترل بهتری روی قابلیت‌های جستجو داشته باشیم، بدون شک استفاده از روش explicit بهترین گزینه خواهد بود. اگرچه Elasticsearch منعطف بوده و اجازه می‌دهد از مزیت‌های هر دو روش در کنار هم نیز استفاده کنیم.

dynamic mapping چگونه کار می‌کند

هنگامی که field جدیدی در document شناسایی می‌شود، در صورتی که ویژگی dynamic در index فعال باشد، Elasticsearch بر مبنای نوع داده‌ی field در JSON ارائه شده، datatype مناسب را برای field حدس می‌زند. پارامتر dynamic در کلید mappings تعیین می‌کند که رفتار Elasticsearch در index مورد نظر ضمن شناسایی فیلد جدید چگونه باشد:

PUT sample-index
{
	"mappings": {
		dynamic: true;
	}
}

این پارامتر می‌تواند مقادیر زیر را بگیرد:

  • true: مقدار پیش‌فرض است. فیلد‌های جدید به صورت خودکار تشخیص داده شده و در mapping اضافه می‌شوند.
  • false: فیلد‌های جدید که در mapping تعریف نشده باشند، به mapping اضافه نشده و بدون اینکه ایندکس شوند (توسط analyzer ها تجزیه شوند) ، فقط در source_ ذخیره خواهند شد.
  • strict: اگر فیلد جدیدی تشحیص داده شود، باعث بروز خطا شده و فقط وفقط فیلد‌هایی که در mapping تعیین شده باشند، امکان مقداردهی دارند. در این شرایط Elasticsearch همچون یک پایگاه داده‌ی ساختاریافته (structured) عمل می‌کند.
Elasticsearch برای حدس زدن datatype مناسب برای هر فیلد، مطابق جدول زیر عمل می‌کند (ستون سمت چپ datatype های Elasticsearch است که در قسمت بعدی با جزییات آن‌ها آشنا می‌شویم):

تشخیص تاریخ در mapping

اگر پارامتر date_detection (تشخیص تاریخ) در mapping فعال باشد (پیش‌فرض فعال است)، مقادیر فیلد‌های متنی در document، با فرمت تعریف شده در پارامتر dynamic_date_formats مقایسه شده و در صورتی که تطبیق داشته باشد، به صورت خودکار فیلد از نوع date در mapping اضافه می‌شود. مقدار پیش‌فرض پارامتر dynamic_date_formats به صورت زیر است:

["strict_date_optional_time", "yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]

طبق فرمت بالا علاوه بر دو فرمت "yyyy/MM/dd HH:mm:ss Z" و "yyyy/MM/dd Z"، فرمت‌های زیر نیز قابل قبول است:

"yyyy-MM-dd'T'HH:mm:ss.SSSZ" 

"yyyy-MM-dd"

پارامتر‌های date_detection و dynamic_date_format در کلید mapping در API ایجاد index قابل تنظیم هستند:

PUT sample-index
{
	"mappings": {
		"date_detection": false,
		"dynamic_date_formats": ["MM/dd/yyyy"]
	}
}

تشخیص فیلد عددی در mapping

اگر numeric_detection در mapping فعال باشد (پیش‌فرض غیرفعال است!)، مقادیر عددی که به صورت متنی باشند، به صورت خودکار و طبق جدول تبدیل datatype که بالاتر اشاره شد، تبدیل می‌شوند.

پارامتر numeric_detection نیز در کلید mappings قابل مقداردهی است:

PUT sample-index
{
	"mappings": {
		"numeric_detection": false
	}
}

explicit mapping چگونه کار می‌کند

هنگام ایجاد یک index می‌توان mapping مورد نظر را برای index تعریف کرد. در این شرایط فیلد‌هایی که در mapping تعریف شده باشند، مطابق همان ویژگی‌هایی که برای آن‌ها تعریف شده است، ایندکس خواهند شد و مابقی فیلد‌های جدیدی که تشخیص داده شوند، طبق قوانین dynamic mapping بررسی خواهند شد.

برای تعیین فیلد‌های mapping باید از کلید properties در کلید mappings استفاده کرد و برای هر فیلد، یک کلید با نام مورد نظر آن ایجاد می‌کنیم. برای مثال در index زیر می‌خواهیم فیلد‌های title و age را در mapping تعریف کنیم:

PUT sample-index
{
	"mappings": {
	   "properties": {
	      "age": {"type": "integer"},  
	      "title": {"type": "text"}
	   }
	}
}

برای هر فیلد که به صورت یک کلید در properties تعریف می‌شود، یک object به عنوان مقدار درنظر می‌گیریم و داخل آن تنظیمات analyzer ،type و سایر پارامتر‌های mapping را تعریف می‌کنیم. برای مثال در نمونه‌ی بالا، برای فیلد datatype ،age از نوع integer و برای فیلد datatype ،title از نوع text تعریف شده است که هرکدام ویژگی‌های خاص خود را دارند. در قسمت بعدی جزییات مهم‌ترین datatype ها و همچنین برخی پارامتر‌های مهم در mapping هر فیلد را بررسی خواهیم کرد.

دوره در حال تکمیل است ... rocket