من این سوال رو به عنوان کسی که در پروژههای متعددی از جلمه جوابکو از الستیکسرچ استفاده کرده و قبل از اون هم از تجربه استفاده از Apache Solr رو داشته جواب میدم.
الستیکسرچ در واقع یک نوع پایگاه داده یا Database هست که مهمترین کاربردش جستجوی متن هست. درسته که بانکهای دادهای مثل MySql و یا MongoDB امکان ایندکس کردن برای جتسجوی Fulltext رو میدن اما سرعتشون در مقایسه با ElasticSearch بسیار پایینه مخصوصا وقتی که تعداد دادهها از مرحله ۱۰ میلیون رکورد بیشتر میشه و یا حجم متنها خیلی طولانی هست.
یکی از قابلیتهای خیلی خوب ElasticSearch امکان تعریف آنالایزر (Analyzer) هست. مثلا در متون فارسی نیمفاصله و یا انواع حرف «کاف» و «ی» و اعداد (فارسی و عربی) وجود داره. در ElasticSearch با تعیین یک آنالایزر مناسب وقتی دادهها ایندکس میشن خودش دو حالت رو ایندکس میکنه یا یکی از حالتها رو به دیگری تغییر میده. در نتیجه به عنوان مثال چه کاربر از نیمفاصله استفاده کنه چه از فاصله میتونه یک نتیجرو نشون بده. میتونید این موضوع رو با جستجوی «برنامهنویسی» و «برنامه نویسی» در جوابکو امتحان کنید. همینطور از آنالیزورها میشه برای پیدا کردن حالتهای دیگر یک فعل یا اسم استفاده کرد. مثلا میتونید کاری کنید که اگر فعل «خوابیدن» استفاده شد، «خواب» رو هم جستجو کنه و یا اگر «درختان» جستجو شد «درخت» هم جستجو بشه.
از طرف دیگه در متنهای طولانی امکان نمایش Highlight رو به شما میده. یعنی مثل گوگل وقتی یک کاربر یک کلمه یا عبارت رو جستجو میکنه میتونید بخشی که این عبارت در متن بزرگ به کار رفترو نشون بدید به کاربر.
همینطور خیلی ساده میشه با استفاده از تعیین Boost ترتیب نتایج رو تغییر داد! مثلا تعیین کرد در تیتر و متن یک وبلاگ جستجو شه اما به تیتر ارزش بیشتری داده شه که این موارد انجامش در پایگاههای داده دیگه خیلی سخته.
از کاربردهای دیگر ElasticSearch میشه به امکان پیدا کردن موارد مشابه (Similar) یک داده اشاره کرد. یعنی خیلی ساده میتونید یه داده بهش بدید و بگید کدوم دادههای دیگه بر اساس تیتر و متن شبیه این داده هست. خود ElasticSearch با توجه به تمام دادههای شما از TF/IDF استفاده میکنه و موارد مشابه رو نشون میده. یعنی اگر مثلا ببینه از یک کلمه (مثلا کلمه جواب) خیلی زیاد استفاده شده در تمام متنها ارزش کمتری بهش میده برای پیدا کردن موارد مشابه.
خوبی دیگش امکان تشخیص خودکار جنس اجزای مختلف داده شماست. الستیک سرچ یک دیتابیس Document-oriented هست. یعنی شما بهش یک دادرو به صورت فایل JSON میدید و بقیه کارها مثل ایندکس کردن رو خودش انجام میده و وقتیم که نیاز داشته باشید کل اون دادرو به صورت JSON برای شما با توجه به Queryتون میفرسته. وقتی شما یک فایل JSON به ElasticSearch میدید خودش سعی میکنه متوجه بشه که مثلا سن یک عدد هست و تاریخ تولد یک تاریخه و اسم یک رشته. البته برای کارهای جدیتر بهتره این کار رو خودتون دستی به عنوان یک Mapping بهش بدید اما برای کارهای سریع این موضوع خیلی به تولید محصول کمک میکنه.
در الاستیک سرچ امکان Scale کردن هم خیلی ساده هست و میتونید روی چندین نود مختلف اجراش کنید.
با تمام این محاسن نمیشه از الستیک سرچ به عنوان بانک اطلاعاتی اصلی استفاده کرد! یعنی خیلی وقتها تغییر دادن توی ساختار Documentها یا به اصتلاح Schemaشون به سادگی امکان پذیر نیست و باید اصطلاحا از بانک اطلاعات اصلیتون تمام دادهها رو Reindex کنید.
در جوابکو در حال حاضر از MongoDB استفاده میکنیم و تمام اطلاعات ابتدا در مونگو ذخیره میشوند ولی با استفاده از یک Library ساده (mongoose۹۷ و پلاگین mongoosastic۱۲۲) تمام دادههارو به ElasticSearch هم منتقل میکنم. یعنی هر بار که سوال جدیدی پرسیده میشه نسخه اصلی روی مونگو وجود داره و نسخهای هم روی ElasticSearch ایندکس میشه. همچنین وقتی یه سوال تغییر میکنه هم ElasticSearch رو بروز میکنیم. وقتی جستجو رو انجام میدید ما دیگه کاری به مونگو نداریم و فقط ElasticSearch استفاده میشه.
همین کار رو خیلی ساده میتونید با استفاده از لایبراری Elastica۱۸۱ در PHP انجام بدید. اگر از یک ORM مثل Doctrine دارید استفاده میکنید با تعیین یک Hook ساده قبل از Create، Update و Delete و استفاده از Elastica میتونید تمام اطلاعاتی که در دیتابیس اصلیتون ذخیره میشرو در ElasticSearch ذخیره کنید.
سختترین بخش یادگیری ElasticSearch شاید نحوه Query گرفتن و ایجاد Mapping باشه. برای همین پیشنهاد میکنم به ترتیب مقالات زیر رو قبل و یا در حین استفاده از الستیکسرچ بخونید:
- ایجاد مپینگ در ElasticSearch۴۲۵
- تایپهای (Type) مختلف در ElasticSearch۳۱۱
- روشهای نوشتن Query در ElasticSearch۳۶۸
مخصوصا مورد سوم (خودش و چند صفحه بعدش) خیلی مهم هست چون در الاستیک سرچ یک Query رو میشه به چندین مدل نوشت که میتونه کمی گیج کننده باشه.