چرا جست و جو مهم است؟
انسان، موجودی کنجکاو و بی قرار است که مدام به دنبال یادگیری و پیدا کردن جواب سوال های مختلف میباشد. به عنوان مثال یافتن یک رستوران جدید برای غدا خوردن، خرید هدیه ای خوب برای بهترین دوست خود و یا چیزهایی که زندگی ما را بهتر، و ما را خوشحال تر میکنند. راضی نگه داشتن این حس کنجکاوی هیچ گاه راحت تر از اکنون نبوده، زیرا در هر لحظه تمام اطلاعات دنیا در دستان ما وجود دارد.
مطالعات اخیر نشان میدهد که متداول ترین کاری که با گوشی های هوشمند انجام می شود استفاده از موتورهای جست و جو است. انجام این کار باعث برطرف شدن حس کنجکاوی که در ما وجود دارد میشود. طبق آمار، در کشور سوئد 68 درصد از مشتری ها قبل از خرید یک کالا آن را در اینترنت جست و جو می کنند و این نشان می دهد که چقدر قابلیت جست و جو برای یک کسب و کار اینترنتی مهم است.
چالش های جست و جو
تصور کنید که به دنبال یک تیشرت سفید می گردید. به بخش جست و جو یک فروشگاه اینترنتی رفته و عبارت "تیشرت سفید" را جست و جو می کنید. همه نتایجی که به شما نشان داده می شود تیشرت هستند اما رنگ آن ها سفید نیست، زیرا در عنوان محصولات سایت رنگ تیشرت ها ذکر نشده و از آنجایی که عبارت شما تنها در عناوین محصولات جست و جو شده، نتیجه مرتبط با آن را مشاهده نکردید. حال تصور کنید اشتباهی به جای عبارت تیشرت سفید "نیشرت سفید" را جست و جو میکردید و سایت هیچ نتیجه ای به شما نشان نمیداد و یا پس از این که عبارت را جست و جو کردید زمان زیادی صرف میشد تا نتایج به شما نشان داده شوند. همه این ها دلایلی است که باعث می شود شما آن سایت را ترک کنید زیرا نمی توانید در آن، محصولی که در ذهن خود متصور شده بودید را بیابید. علی رغم این که آن محصول یک جایی در سایت وجود دارد.
انواع دیتابیس
پیش از اینکه درمورد full text search صحبت کنیم بهتر است با انواع دیتابیس ها آشنا شویم. با توجه به نیازمندی های گسترده ای که در دیتابیس ها وجود دارد انواع مختلفی از آن در دنیای امروز وجود دارد. به طور کلی می توان آن ها را به دو دسته رابطه ای و غیر رابطه ای تقسیم کرد. برخی از دیتابیس های رابطه ای که در دسته SQL قرار می گیرند عبارت اند از :
· MySQL
· SQL Server
· Oracle
· PostgreSQL
· SQLite
دیتابیس های غیر رابطه ای که در دسته NoSQL قرار میگیرند انواع مختلفی دارند که عبارت اند از:
· Key-Valueها مانند Redis
· Wide Column ها مانند Cassandra
· Document based ها مانند MongoDB
· Graph ها مانند Neo4J
از آنجایی که این مطلب درمورد full text search می باشد به همین مقدار توضیح درمورد انواع دیتابیس بسنده میکنیم. برای آشنایی بیشتر می توانید به مقالهی با تفاوت های دیتابیس های SQL و NoSQL مراجعه کنید.
Full text search چیست؟
یک شیوه پیشرفته جست و جو در دیتابیس است. برخلاف جست و جوی عادی که تطبیق یک کلمه در مستند را با سرعت کمی پیدا می کند، یک موتورfull text search ابتدا موقعیت مکانی تمام کلمات یک مستند را index می کند تا جست و جوی کاربر توسط index ها به نتیجه برسد و لازم نباشد کل یک مستند برای هر جست و جو پیمایش شود. در این مطلب سعی می کنیم تا به درک مناسبی از full text search و تفاوت آن با جست و جوی عادی برسیم.
سایت های معروفی که از قابلیت full text search استفاده می کنند:
از آن جایی که full text search بسیار کاربردی و مهم است سایت های زیادی از این قابلیت استفاده می کنند. سایت های زیر بخشی از معروف ترین آن ها هستند.
چرا به جای search عادی از full text search استفاده کنیم؟
هنگامی که به دیتابیس ها query می زنیم پاسخ مورد انتظار ما تنها دو حالت دارد. اگر داده موجود است، آن را در پاسخ می بینیم و اگر موجود نیست، در پاسخ دیده نمی شود. به طور کلی، درون دیتابیس ها اطلاعاتی را ذخیره می کنیم تا مدتی بعد آن ها را بخوانیم. به همین دلیل هیچ نقطه مبهم و غیر شفافی در آن ها وجود ندارد. یک مقدار، یا در دیتابیس موجود است یا نیست.
تصویر 1- عدم وجود نقطه مبهم در دیتابیس ها و عملکرد صفر و یکی آن ها
اما هنگامی که ما یک عبارت را جست و جو می کنیم این قاطعیت و صفر و یکی بودن مد نظر ما نیست. بلکه به دنبال نتایجی با تفاوت نامحسوس نیز هستیم. به نحوی ما یک مفهوم و تصور را جست و جو می کنیم و به دنبال یک عبارت دقیق نمی گردیم.
تصویر 2- نشان دادن عدم قطعیت نتایج هنگام جست و جو
خب اگر شما کار با دیتابیس رابطه ای مانند MySQL را بلد باشید ممکن است بگویید برای فراهم کردن این نوع از نتایج که مطابقت کامل با عبارت جست و جو شده ندارد و نتایج مرتبط را هم شامل می شود از دستوری مانند زیر استفاده می کنیم.
تصویر 3 کوئری جست و جو در MySQL
اما این مدل از جست و جو به دو دلیل ناموفق خواهد بود:
1- کارایی (performance):
اگر شما داده های خود را در یک دیتابیس رابطه ای ذخیره کردید و می خواهید یک عبارت را با سرعت زیاد پیدا کنید، معمولا برای یک ستون خاص Index اضافه می کنید که خیلی شبیه به دفترچه تلفن می ماند. تصور کنید در یک دفترچه تلفن به دنبال شماره شخصی می گردید. اگر بدانید نام خانوادگی آن شخص با چه حرفی آغاز می شود دفترچه تلفن کمک خوبی به شما می کند و به سرعت شخص مورد نظر خود را پیدا می کنید. اما اگر تنها بخشی از نام خانوادگی شخص را می دانید و آن هم بخش اول نیست یا فقط نام کوچک شخص را می دانید، دفترچه تلفن هیچ کمکی به شما نمی کند و شما مجبور به گشتن کل دفترچه می شوید و هرچه شماره های بیشتری در این دفترچه داشته باشید باید زمان بیشتری صرف پیدا کردن شماره آن شخص کنید. این همان اتفاقی است که در دیتابیس های رابطه ای می افتد.
2- قابلیت هایی که از دست می دهید:
شما قابلیت هایی مثل امتیازدهی بر اساس کیفیت نتیجه یا پیدا کردن نتایجی که مربوط به آن عبارت اند یا با آن مترادف اند و یا نتایجی که با درست شدن غلط املایی عبارت جست و جو شده ممکن است به دست آید را از دست می دهید. این ها بخشی از قابلیت های full text search هستند که در این مقاله آن ها را توضیح می دهیم.
احتمالا بعد از مطالعه بخش بالا متوجه شدید که برای استفاده از قابلیت ها ی full text search، هنگام ذخیره اطلاعات در دیتابیس نیاز به انجام کار بیشتری است. به طور عادی وقتی می خواهید یک رکورد در دیتابیس ذخیره کنید آن را از کاربر گرفته و ذخیره می کنید. اما در full text search کارهای بیشتری انجام می شود که آن ها را در بخش "full text search چگونه کار می کند؟" توضیح داده ایم.
اصطلاحات مشترک دنیای full text search با دیتابیس های رابطه ای
با وجود این که دیتابیس ها و موتورهای full text search، برای کارهای متفاوتی ساخته شده اند اما یک سری اصطلاحات مشترک بین آن ها وجود دارد که در این بخش آن ها را توضیح می دهیم.
• پردازش query :
برای هردوی این فناوری ها می توان کوئری نوشت تا توسط آن ها پردازش شده و اطلاعات مورد نیاز به دست آید. البته دیتابیس های رابطه ای معمولا syntax (نحوه نگارش) ساختاریافته تری نسبت به موتورهای full text search دارند.
• بارگذاری اطلاعات :
مانند دیتابیس رابطه ای، اطلاعات باید در سیستم های full text نیز بارگذاری شود. مانند سیستم های رابطه ای نحوه سازماندهی و بارگذاری داده ها می تواند تاثیر مهمی در موفقیت برنامه داشته باشد.
• Index کردن داده ها :
هنگامی که اطلاعات در دیتابیس رابطه ای بارگذاری می شود باید برای بهبود کارایی دیتابیس آن ها را index کنیم. این مسئله برای سیستم های full text نیز صدق می کند. یک سیستم full text معمولا index های بیشتری نسبت دیتابیس رابطه ای ایجاد می کند زیرا آن ها برای هر کلمه در یک متن یک index ایجاد می کنند. البته در این سیستم ها index کردن ضروری است و تنها برای بهبود کارایی انجام نمی شود.
اصطلاحات رایج در دنیای full text search
ممکن است هنگام مطالعه مطالب در مورد full text search با اصطلاحاتی مواجه شوید که در دیتابیس رابطه ای وجود ندارند در این بخش مهم ترین آن ها را توضیح داده ایم.
• Relevance scoring :
هر موتور full text search مجموعه ای از الگوریتم ها و قوانینی دارد که طبق آن ها مرتبط بودن داده ها با عبارت جست و جو شده را محاسبه می کند پس از انجام این محاسبات، به نتایج به دست آمده بر اساس میزان مرتبط بودن با عبارت جست و جو شده یک امتیاز تعلق می گیرد که به آن relevance score می گویند. نحوه محاسبه دقیق این امتیاز در هر موتور full text متفاوت است و معمولا شامل محاسبات پیچیده ریاضی می شود.
• Weighting :
هنگامی که کوئری search خود را در موتورهای full text می نویسیم می توانیم به یک عبارت یا فیلد خاص وزن بیشتر یا کمتری اختصاص دهیم. وقتی ما وزن یک عبارت یا فیلد را تغییر می دهیم، هنگام محاسبه relevance score برای نتایج، ارزش آن عبارت یا فیلد به همان میزان تغییر می کند.
full text search چگونه کار می کند؟
همان طور که گفته شد هنگام ذخیره داده ها جهت انجام full text search نسبت به دیتابیس های رابطه ای یا NoSQL کارهای بیشتری انجام می شود. در یک دیتابیس عادی اطلاعات را می دهیم تا آن ها در جایی مثل یک فایل یا درون memory مستقیما ذخیره شوند. اما برای full text search این گونه نیست و نیاز است مراحلی طی شود. این مراحل عبارت اند از:
1- حذف هرگونه قالب بندی (formatting) :
قالب بندی می تواند چیزی مانند کدهای HTML باشد که یک بخش از متن را bold کرده است. از آنجایی که هیچکس نمی خواهد تگ های HTML را جست و جو کند و همچنین این استایل ها به محتوای یک متن معنی خاصی اضافه نمی کنند موتورهای full text search آن ها را از متن حذف می کنند.
2- نشانه گذاری (tokenize کردن) :
نشانه گذاری به این معنی است که در یک جمله هرگونه فاصله و نقطه گذاری را نادیده بگیریم و هر کلمه از آن جمله را بیرون بکشیم. موتورهای full text تنها به آن کلمات بیرون کشیده شده نگاه می کنند. بنابراین یک موتور full text جمله ما را به معنای واقعی متوجه نمی شود و نمی داند منظور آن جمله چیست بلکه کلمات آن را بیرون می کشد و روی آن ها کار انجام می دهد.
3- حذف برخی از کلمات بیهوده (stop words):
حال که به یک سری کلمات مستقل رسیده ایم نوبت به حذف کلماتی می رسد که بسیار کوچک اند و در هر متنی حضور دارند اما معنی کمی به متن اضافه می کنند. اگر بخواهیم این کلمات را index کنیم، حجم index ما، به طور چشم گیری زیاد خواهد شد. در زبان انگلیسی کلماتی مانند: a-and-if-not-this-that-the و... به عنوان stop word شناخته می شوند.
4- استخراج ریشه (stemming):
در این مرحله ریشه اصلی هر کلمه به دست آورده می شود. به عنوان مثال اگر اسمی در حالت جمع باشد آن را به حالت فرد تبدیل می کنیم تا دیگر تفاوتی بین عبارت جمع و فرد هنگام جست و جو نباشد.
5- ذخیره مترادف ها:
اکثر کاربران انتظار دارند هنگامی که یک واژه را جست و جو می کنند نتایجی مرتبط با آن مفهوم دریافت کنند نه فقط نتایجی که شامل آن عبارت است. مانند دو کلمه ماشین و خودرو، هر دو آن ها یک معنی می دهند و انتظار می رود هرکدام از آن ها که جست و جو شد نتیجه مرتبط دریافت شود.این مرحله اختیاری است و معمولا به domain هر پروژه و کاری که می خواهیم انجام دهیم بستگی دارد. لیست مترادف ها را خودمان باید فراهم کنیم و موتورهای full text هیچ گونه لیست عمومی از مترادف کلمات در خود ندارند.
اکنون شما اطلاعات مناسبی از فرآیند ذخیره داده ها در یک موتور full text search کسب کرده اید. حال می خواهیم مسیری که هنگام جست و جوی یک عبارت طی می شود را مورد بررسی قرار دهیم.
همان طور که در این مطلب ذکر کردیم موتورهای full text search یک سری قابلیت ها را برای ما فراهم می کنند. یکی از آن ها fuzzy searching است. به این معنی که اگر عبارت جست و جو شده با کلماتی که در index موتور full text search وجود دارند کمی تفاوت داشته باشد همچنان نتایج به ما نشان داده می شوند. این قابلیت هنگامی که عبارت جست و جو شده غلط املایی دارد بسیار کاربردی است.
همچنین می توان به یک عبارت یا فیلد وزن بیشتری تعلق داد تا نتایجی که آن عبارت را دارند یا از آن فیلد هستند مرتبط تر در نظر گرفته شوند. این گونه قابلیت ها بین موتورهای مختلف که کار full text search را انجام می دهند متفاوت است اما یک فرآیند مهم و مشترک وجود دارد که امتیاز (score) نتایج به دست آمده را تعیین می کند. مراحل این فرآیند عبارت اند از:
1- تکرار یک کلمه (Term frequency)
هنگامی که شما یک کلمه را جست و جو می کنید اگر آن کلمه در یک مستند دفعات زیادی تکرار شده باشد احتمالا آن مستند ارتباط بیشتری با جست و جوی شما دارد نسبت به مستندی که آن کلمه یک دفعه در آن تکرار شده است.
2- معکوس تکرار در مستند (Inverse document frequency)
طبق این قانون کلمات کمیاب ارزش بیشتری دارند. به عنوان مثال اگر کلمه "سلام" سراسر یک مستند 20 بار تکرار شده باشد و کلمه "سلامتی" در سراسر آن 3 بار تکرار شده باشد، ارزش کلمه "سلامتی" در آن مستند بیشتر از کلمه "سلام" است. به عبارتی دیگر آن مستند بیشتر به "سلامتی" مربوط است تا به "سلام". توجه داشته باشید که این قانون جهت تعیین ارتباط هر کلمه به مستند است و برخلاف Term frequency مستقیما با عبارت جست و جو شده ارتباط ندارد. این مقدار به صورت نمایی کاهش می یابد. به عنوان مثال: ارتباط کلمه ای که 1000 بار در مستند تکرار شده است، با آن مستند تقریبا صفر است. اما ارتباط کلمه ای که 200 بار تکرار شده است، تقریبا 2 می باشد. این اعداد به دلیل وجود لگاریتم در فرمول محاسبه، به صورت نمایی تغییر می کنند.
3- مقیاس طول فیلد (Field-length norm)
طبق این قانون اگر کلمه جست و جو شده در یک فیلد کوتاه، پیدا شده باشد، ارزش آن بیشتر از زمانی است که در یک فیلد طولانی (به عنوان مثال یک متن بلند) پیدا شود.
چه دیتابیس هایی قابلیت full text search دارند؟
با توجه به اهمیت و محبوبیت بالای full text search در دنیای امروز، تعداد زیادی از دیتابیس ها قابلیت full text search را به کاربران خود ارائه می دهند.
دیتابیس های SQL معروف، که از full text search پشتیبانی می کنند عبارت اند از :
• MySQL
• PostgreSQL
• SQL server
• MariaDB
• SQLite
دیتابیس های NoSQL معروف که از full text search پشتیبانی می کنند عبارت اند از :
• Elasticsearch
• MongoDB
• Redis
• Neo4J
البته دیتابیس هایی که از full text search پشتیبانی می کنند تنها محدود به این دو لیست نیستند و در اینجا معروف ترین ها ذکر شدند.
کدام دیتابیس برای انجام full text search مناسب تر است؟
احتمالا مصرع معروف "هر کسی را بهر کاری ساخته اند" را شنیده اید. در دنیای دیتابیس ها نیز می توان گفت هر دیتابیسی را بهر کاری ساخته اند. هر دیتابیس در یک حوزه خاص بسیار خوب عمل می کند، به عنوان مثال: جهت پیاده سازی یک سیستم cache از Redis و Memcached که از نوع in-memory هستند و سرعت بالایی دارند، استفاده می شود. برای انجام search نیز به همین ترتیب دیتابیس هایی وجود دارد که هدف اصلی آن ها، انجام جست و جو است و دارای موتور جست و جوی قدرت مندی هستند. از معروف ترین آنها می توان به Elastic search، Solr و Sphinx اشاره کرد که بین آن ها Elastic search، از محبوبیت بیشتری برخورد دار است.
اما با وجود اینکه دیتابیسی مانند MySQL، قابلیت full text search را ارائه می کند، چه دلیلی دارد از دیتابیس دیگری برای search استفاده کنیم؟ در این بخش سعی می کنیم پاسخ مناسبی برای این سوال پیدا کنیم.
مقایسه موتورهای full text search با دیتابیس های رابطه ای
سیستم هایی که ویژه انجام full text search ایجاد شده اند، جست و جوی یک یا چند کلمه میان حجم عظیمی از متن های ساختاریافته، نیمه ساختاریافته و غیر ساختاریافته را با سرعت زیاد انجام می دهند. این سیستم ها قابلیت های بسیار خوبی در زمینه امتیازدهی و کیفیت سنجی نتایج، بر اساس ارتباط آن ها با عبارت جست و جو شده، در اختیار ما قرار می دهند تا بتوانیم بر آن اساس نتایج خود را مرتب سازی کنیم. این قابلیت در شرایطی که تعداد نتایج جست و جو بسیار زیاد است کاربرد زیادی دارد. همچنین این سیستم ها از پردازش کننده های زبان استفاده می کنند تا به کمک الگوریتم های قوی مفهوم جست و جوی کاربر را بهتر متوجه شده و نتایج دقیق تری ارائه کنند.
دیتابیس های رابطه ای از طرفی دیگر در ذخیره و ایجاد تغییر روی داده های ساختاریافته و هر چیزی که در قالب جدول و ستون قرار دارد برتری دارند. اکثر این دیتابیس ها از جست و جوی کلمات کلیدی، حتی در فیلدهای متنی، پشتیبانی می کنند اما رتبه بندی نتایج بر اساس میزان مرتبط بودن با عبارت جست و جو، به خوبی و پیچیدگی سیستم هایی که ویژه full text search ایجاد شده اند، نیست. همچنین تنها درصورتی کارایی (performance) این دیتابیس ها برای full text search مناسب است که به سؤالاتی که کاربر قرار است از سیستم جست و جوی ما بپرسد، آگاهی داشته باشیم و ساختار دیتابیس خود را برای آن سوالات آماده کرده باشیم. در غیر این صورت دیتابیس به کندی پاسخ نیازهای ما را می دهد و این مسئله باعث ایجاد تجربه ای بد برای کاربر خواهد شد. همچنین در نظر داشته باشید که حتی اگر از قبل بدانیم کاربر چه سؤالاتی را خواهد پرسید و خود را برای آن آماده کرده باشیم، ممکن است نیازهای کاربر در طول زمان تغییر کند و این اتفاق مدیریت دیتابیس را سخت تر می کند، چرا که سیستم دارای پتانسیل مناسبی جهت گسترش نمی باشد.
چه زمان در پروژه خود از دیتابیس مخصوص full text search استفاده کنیم؟
نیازمندی های برنامه، موجب می شود تا دیتابیسی که مخصوص full text search ساخته شده است را به جای یک دیتابیس رابطه ای انتخاب کنیم. برخی از این نیازمندی ها عبارت اند از:
• برنامه حجم زیادی از داده های متنی را index می کند.
• داده هایی که می خواهیم روی آن ها جست و جو انجام دهیم در منابع مختلفی وجود دارند.
• برنامه باید قابلیت جست و جوی بسیار منعطفی داشته باشد.
• در دیتابیس رابطه ای، میزان مرتبط بودن نتایج به حد مورد انتظار نرسیده است.
• کوئری های زیاد و سنگینی به دیتابیس برای انجام جست و جو زده می شود.
• تجربه کاربری مناسب از نیازمندی های اصلی پروژه است.
جمع بندی
در این مقاله اهمیت قابلیت جست و جو در برنامه های امروزی مطرح شد و تلاش کردیم تا علاوه بر اینکه اطلاعات مناسبی از چگونگی کار سیستم های full text search ارائه دهیم، تفاوت میان این سیستم ها و جست و جوی عادی را نیز مطرح کنیم. از میان فناوری های مطرح شده در زمینه full text search دیتابیس elastic search از محبوبیت بالا و امکانات بسیار خوبی برخوردار است. که آموزش کامل و گام به گام elastic search را در قسمت دوره های سکان آکادمی می توانید بخوانید. در صورت تصمیم به استفاده از قابلیت full text search پیشنهاد می شود درمورد این دیتابیس بیشتر مطالعه انجام دهید.