جستجو با الستیک سرچ
الستیک سرچ یک موتور جستجو و انبار سند است: سندهای JSON را به آن میدهید و او سندهایی را که با پرسمان جورند پیدا میکند، رتبه میدهد و به هر شکلی که بخواهید میشمارد. این درس با بستهی الستیک سرچ یک فهرست کوچک کتابخانه میسازد، از نخستین اتصال تا بارگذاری دستهای و اس کیو ال.
یک خوشه برای گفتگو
این بسته با الستیک سرچ ۷ و ۸، با Elastic Cloud و با OpenSearch، روی HTTP ساده یا TLS و بدون هیچ کتابخانهی بیرونی گفتگو میکند. برای آزمایش، یک گره در داکر کافی است:
docker run -d -p 127.0.0.1:9200:9200 -e discovery.type=single-node -e xpack.security.enabled=false docker.elastic.co/elasticsearch/elasticsearch:8.15.3
این گره بدون رمز روی http://localhost:9200 پاسخ میدهد. نمونههایی که به خوشهی در حال اجرا نیاز دارند فقط بررسی میشوند؛ نمونههایی که JSON میسازند یا پاسخ را میخوانند همینجا اجرا میشوند و خروجی واقعیشان دیده میشود.
اتصال
اتصال(نشانی) شکل کوتاه است. برای بیشتر از آن یک پیکربندی را پر کنید و به کارخواه تازه بدهید: چند گره، نام کاربری و رمز، کلید API، توکن حامل، فایل مرجعی که گواهی خوشه را امضا کرده، مهلت و تعداد تلاش دوباره. نشانی گره خودش هم میتواند اعتبارنامه داشته باشد، مانند https://user:pass@host:9200.
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
ناپایا پیکر := الستیک سرچ.پیکربندی پیشفرض()
پیکر.nodes = وکتور {} برگردان وکتور<رشته>
پیکر.nodes.بیفزا("https://es-1.example.com:9200")
پیکر.nodes.بیفزا("https://es-2.example.com:9200")
پیکر.username = "elastic"
پیکر.password = "s3cret"
پیکر.ca_file = "/etc/elasticsearch/certs/http_ca.crt"
پیکر.timeout_ms = 10000
ناپایا ک := الستیک سرچ.کارخواه تازه(پیکر)
اگر وارونه الستیک سرچ.پینگ(ک):
سرچاپ "no answer:"، الستیک سرچ.خطا(ک)
برگشت
پایان
آگاهی := الستیک سرچ.دریافت اطلاعات(ک)
سرچاپ آگاهی.distribution، آگاهی.version، الستیک سرچ.سلامت خوشه(ک).status
الستیک سرچ.بستن(ک)
پایانساختن کارخواه به شبکه دست نمیزند. پینگ میپرسد خوشه پاسخ میدهد یا نه، دریافت اطلاعات نام و نسخه و توزیع آن را برمیگرداند و سلامت خوشه وضعیت green، yellow یا red را. وقتی کارتان تمام شد بستن کارخواه و اتصالهایی را که باز نگه داشته آزاد میکند.
| چیزی که دارید | به کار ببرید |
|---|---|
| یک گرهی محلی بدون امنیت | اتصال("http://localhost:9200") |
| نام کاربری و رمز | اتصال با رمز(نشانی، کاربر، رمز) |
| کلید API | اتصال با کلید(نشانی، کلید)، کدگذاری شده یا به شکل id:key |
| استقرار Elastic Cloud | اتصال ابری(شناسهی ابری، کلید) |
| توکن حساب سرویس | پیکربندی با bearer |
| گواهی خودامضای خوشه | پیکربندی با ca_file |
ذخیره و خواندن سند
سند یک شیء JSON است که با یک شناسه در یک نمایه ذخیره میشود. سندها و بندهای پرسمان مقدارهای رشته سادهایاند که JSON دارند، پس میتوانید آنها را دستی بنویسید، با بستهی جیسون بسازید یا از سازندههای همین بسته استفاده کنید. ایجاد نمایه نمایه را با نگاشتش میسازد؛ نمایه کردن سند را ذخیره میکند؛ دریافت آن را برمیگرداند؛ بهروزرسانی فیلدها را در آن ادغام میکند و حذف آن را برمیدارد.
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
ناپایا ک := الستیک سرچ.اتصال("http://localhost:9200")
طرحنگاشت := `{"mappings":{"properties":{"title":{"type":"text"},"author":{"type":"keyword"},"year":{"type":"integer"}}}}`
اگر وارونه الستیک سرچ.نمایه موجود است(ک، "books"):
الستیک سرچ.ایجاد نمایه(ک، "books"، طرحنگاشت)
پایان
نوشته := الستیک سرچ.نمایه کردن با گزینه(ک، "books"، "1"، `{"title":"Shahnameh","author":"ferdowsi","year":1010}`، الستیک سرچ.گزینهها { refresh = الستیک سرچ.تازهسازی با انتظار })
سرچاپ نوشته.ok، نوشته.result، نوشته.version
س := الستیک سرچ.دریافت(ک، "books"، "1")
اگر س.found:
سرچاپ س.source
پایان
بهروزشده := الستیک سرچ.بهروزرسانی با گزینه(ک، "books"، "1"، `{"year":1011}`، الستیک سرچ.گزینهها { if_seq_no = س.seq_no، if_primary_term = س.primary_term })
اگر وارونه بهروزشده.ok:
سرچاپ "someone else changed it first:"، الستیک سرچ.نوع خطا(ک)
پایان
سرچاپ الستیک سرچ.موجود است(ک، "books"، "1")، الستیک سرچ.شمارش(ک، "books"، "")
الستیک سرچ.حذف(ک، "books"، "1")
الستیک سرچ.بستن(ک)
پایانهر نوشتن یک نتیجه نوشتن برمیگرداند با ok، نتیجه در result (created، updated، deleted)، version تازه و شمارههای ترتیب. اگر if_seq_no و if_primary_term را از یک دریافت بدهید، بهروزرسانی به «مقایسه و جایگزینی» تبدیل میشود: اگر کسی در این فاصله سند را تغییر داده باشد، بهروزرسانی با تعارض نسخه شکست میخورد و تغییر او را بازنویسی نمیکند.
سند تازه فقط پس از تازهسازی نمایه، حدود هر یک ثانیه، قابل جستجو است. گزینهها { refresh = الستیک سرچ.تازهسازی با انتظار } فراخوانی را تا آن لحظه منتظر نگه میدارد که در آزمونها و اسکریپتها به کار میآید.
ساختن پرسمان
هر سازندهی پرسمان یک بند JSON برمیگرداند: تطبیق برای متن کامل، واژه و واژهها برای مقدار دقیق، بازه برای عدد و تاریخ، و همه شرطها، یکی از شرطها، نقیض و پالایش شده برای ترکیب آنها. یک درخواست جستجو پرسمان را همراه اندازه، ترتیب و فیلدهای برگشتی نگه میدارد و بدنه جستجو JSONی را که فرستاده میشود نشان میدهد.
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
ناپایا بایدها := وکتور {} برگردان وکتور<رشته>
بایدها.بیفزا(الستیک سرچ.تطبیق("title"، "book of kings"))
ناپایا پالایه := وکتور {} برگردان وکتور<رشته>
پالایه.بیفزا(الستیک سرچ.بازه("year"، "900"، "1100"))
پالایه.بیفزا(الستیک سرچ.نقیض(الستیک سرچ.واژه("status"، "draft")))
پرسوجو := الستیک سرچ.پالایش شده(الستیک سرچ.همه شرطها(بایدها)، پالایه)
سرچاپ پرسوجو
ناپایا ترتیب := وکتور {} برگردان وکتور<رشته>
ترتیب.بیفزا(الستیک سرچ.مرتب نزولی("year"))
ناپایا نمایان := وکتور {} برگردان وکتور<رشته>
نمایان.بیفزا("title")
نمایان.بیفزا("year")
درخواست := الستیک سرچ.درخواست جستجو { query = پرسوجو، size = 10، sort = ترتیب، source = نمایان }
سرچاپ الستیک سرچ.بدنه جستجو(درخواست)
پایانبندهای فهرست پالایهی پالایش شده فقط تعیین میکنند سند جور است یا نه؛ امتیاز آن را تغییر نمیدهند و الستیک سرچ میتواند نتیجهشان را نگه دارد. متن آزاد را در پرسمان بگذارید و شرطهای دقیق مانند تاریخ، وضعیت و شناسه را در پالایه.
جستجو و خواندن پاسخ
جستجو(ک، نمایه، درخواست) درخواست را اجرا و پاسخ را به یک نتیجه جستجو تجزیه میکند: تعداد کل جورها در total، یافتههای این صفحه در hits که هر کدام id، score، source و highlight دارند، و زمانی که صرف شد.
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
ناپایا ک := الستیک سرچ.اتصال("http://localhost:9200")
ناپایا فیلدها := وکتور {} برگردان وکتور<رشته>
فیلدها.بیفزا("title")
درخواست := الستیک سرچ.درخواست جستجو { query = الستیک سرچ.تطبیق("title"، "kings")، size = 5، highlight = الستیک سرچ.برجستهسازی(فیلدها) }
نتیجه := الستیک سرچ.جستجو(ک، "books"، درخواست)
اگر وارونه نتیجه.ok:
سرچاپ "search failed:"، الستیک سرچ.خطا(ک)
برگشت
پایان
سرچاپ نتیجه.total، "matches in"، نتیجه.took، "ms"
هر یافته در نتیجه.hits:
سرچاپ یافته.id، یافته.score، یافته.source، یافته.highlight
پایان
الستیک سرچ.بستن(ک)
پایانهمین تجزیه جداگانه هم در دسترس است: تجزیه نتیجه جستجو هر پاسخ جستجو را میخواند، برای نمونه پاسخی که با انجام گرفتهاید.
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
بدنه := `{"took":3,"hits":{"total":{"value":2,"relation":"eq"},"max_score":1.8,"hits":[{"_id":"1","_score":1.8,"_source":{"title":"Shahnameh","year":1010}},{"_id":"7","_score":0.9,"_source":{"title":"Garshasp-nama","year":1066}}]}}`
نتیجه := الستیک سرچ.تجزیه نتیجه جستجو(بدنه)
سرچاپ نتیجه.total، نتیجه.total_relation، نتیجه.max_score
هر یافته در نتیجه.hits:
سرچاپ یافته.id، یافته.score، یافته.source
پایان
پایانتجمیع
تجمیع به جای فهرست کردن سندهای جور، آنها را خلاصه میکند: چند کتاب از هر نویسنده، میانگین سال، قدیمیترین کتاب. آنها را با افزودن تجمیع(تجمیعها، نام، تجمیع) بسازید، یکی را با زیرتجمیعها درون یک سطل بگذارید، و با مقدار تجمیع برای یک عدد و سطلهای تجمیع برای گروهها بخوانید. JSON خام هر سطل در raw به مقدار تجمیع در داده میشود تا آنچه درونش است خوانده شود.
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
برایهرنویسنده := الستیک سرچ.زیرتجمیعها(الستیک سرچ.تجمیع واژهها("author"، 5)، الستیک سرچ.افزودن تجمیع(""، "avg_year"، الستیک سرچ.تجمیع میانگین("year")))
ناپایا تجمیعها := الستیک سرچ.افزودن تجمیع(""، "by_author"، برایهرنویسنده)
تجمیعها = الستیک سرچ.افزودن تجمیع(تجمیعها، "oldest"، الستیک سرچ.تجمیع کمینه("year"))
سرچاپ الستیک سرچ.بدنه جستجو(الستیک سرچ.درخواست جستجو { size = 0، aggs = تجمیعها })
پاسخ := `{"hits":{"total":{"value":120,"relation":"eq"},"hits":[]},"aggregations":{"oldest":{"value":940.0},"by_author":{"buckets":[{"key":"ferdowsi","doc_count":70,"avg_year":{"value":1010.0}},{"key":"saadi","doc_count":50,"avg_year":{"value":1258.0}}]}}}`
نتیجه := الستیک سرچ.تجزیه نتیجه جستجو(پاسخ)
سرچاپ "oldest:"، الستیک سرچ.مقدار تجمیع(نتیجه، "oldest")
هر د در الستیک سرچ.سطلهای تجمیع(نتیجه، "by_author"):
سرچاپ د.key، د.doc_count، الستیک سرچ.مقدار تجمیع در(د.raw، "avg_year")
پایان
پایانبا size = 0 وقتی فقط خلاصه مهم است یافتهها برگردانده نمیشوند و درخواست بسیار سبکتر میشود.
بارگذاری سندهای زیاد
فرستادن سندها یکییکی برای هر کدام یک رفت و برگشت هزینه دارد. یک دستهای کنشهای نمایه کردن، ایجاد، بهروزرسانی و حذف را جمع میکند و در یک درخواست میفرستد. پاسخ برای هر قلم میگوید موفق بود یا نه، پس شکست بخشی هیچوقت پنهان نمیماند.
واردسازی رشته
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
ناپایا د := الستیک سرچ.دستهای تازه()
تکرار 3 در ش:
شناسه := رشته.از عدد(ش برگردان صحیح۶۴)
الستیک سرچ.نمایه کردن دستهای(د، "logs"، شناسه، `{"line":` + شناسه + `,"level":"info"}`)
پایان
الستیک سرچ.بهروزرسانی دستهای(د، "logs"، "1"، `{"level":"warn"}`)
الستیک سرچ.حذف دستهای(د، "logs"، "2")
سرچاپ الستیک سرچ.طول دستهای(د)، "actions"
چاپ الستیک سرچ.بدنه دستهای(د)
پاسخ := `{"took":5,"errors":true,"items":[{"index":{"_id":"0","status":201,"result":"created"}},{"index":{"_id":"1","status":201,"result":"created"}},{"index":{"_id":"2","status":201,"result":"created"}},{"update":{"_id":"1","status":200,"result":"updated"}},{"delete":{"_id":"2","status":429,"error":{"type":"es_rejected_execution_exception","reason":"queue is full"}}}]}`
نتیجه := الستیک سرچ.تجزیه نتیجه دستهای(پاسخ)
سرچاپ نتیجه.succeeded، "ok,"، نتیجه.failed، "failed"
هر قلم در نتیجه.items:
اگر وارونه قلم.ok:
سرچاپ "retry"، قلم.action، قلم.id، قلم.error_type
پایان
پایان
پایانبرای بارهای بزرگ، هر هزار کنش یک دسته بفرستید و با بازنشانی دستهای از نو شروع کنید. کارخواه اتصال به هر گره را بین فراخوانیها باز نگه میدارد، پس روی HTTPS هزینهی دستدادن TLS یک بار پرداخت میشود، نه برای هر درخواست.
واردسازی رشته
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
ناپایا ک := الستیک سرچ.اتصال("http://localhost:9200")
ناپایا د := الستیک سرچ.دستهای تازه()
تکرار 10000 در ش:
شناسه := رشته.از عدد(ش برگردان صحیح۶۴)
الستیک سرچ.نمایه کردن دستهای(د، "logs"، شناسه، `{"line":` + شناسه + `}`)
اگر الستیک سرچ.طول دستهای(د) برابر 1000:
نتیجه := الستیک سرچ.اجرای دستهای(ک، د)
سرچاپ نتیجه.succeeded، نتیجه.failed
الستیک سرچ.بازنشانی دستهای(د)
پایان
پایان
اگر الستیک سرچ.طول دستهای(د) > 0:
نتیجه := الستیک سرچ.اجرای دستهای(ک، د)
سرچاپ نتیجه.succeeded، نتیجه.failed
پایان
الستیک سرچ.تازهسازی(ک، "logs")
سرچاپ الستیک سرچ.شمارش(ک، "logs"، "")
الستیک سرچ.بستن(ک)
پایانورق زدن همهی نتیجهها
from و size برای چند صفحهی نخست فهرست نتیجه مناسباند. برای پیمودن همهی جورها، با گشودن نقطه زمانی یک نقطهی زمانی باز کنید، بر اساس فیلدهایی که لازم دارید مرتب کنید، و کل آرایهی sort آخرین یافته را به عنوان search_after بدهید تا صفحهی بعد بیاید. جستجو با نقطهی زمانی یک مقدار یکتای _shard_doc به انتهای sort هر یافته میافزاید، پس هیچ دو یافتهای همرتبه نمیشوند و نیازی به مرتبسازی بر اساس _id نیست. نقطهی زمانی دید را هنگام خواندن ثابت نگه میدارد. جستجوی پیمایشی و پیمایش همین کار را به سبک قدیمیتر انجام میدهند.
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
ناپایا ک := الستیک سرچ.اتصال("http://localhost:9200")
ناپایا ترتیب := وکتور {} برگردان وکتور<رشته>
ترتیب.بیفزا(الستیک سرچ.مرتب صعودی("year"))
نقطه := الستیک سرچ.گشودن نقطه زمانی(ک، "books"، "1m")
ناپایا نشانگر := ""
ناپایا ادامه := درست
تا ادامه:
صفحه := الستیک سرچ.جستجو(ک، ""، الستیک سرچ.درخواست جستجو { size = 500، sort = ترتیب، pit_id = نقطه، pit_keep_alive = "1m"، search_after = نشانگر })
اگر صفحه.hits.طول() برابر 0:
ادامه = نادرست
وگرنه:
هر یافته در صفحه.hits:
سرچاپ یافته.id
پایان
نشانگر = صفحه.hits.بگیر(صفحه.hits.طول() - 1).sort
پایان
پایان
الستیک سرچ.بستن نقطه زمانی(ک، نقطه)
الستیک سرچ.بستن(ک)
پایاناس کیو ال
الستیک سرچ، و افزونهی SQL اوپن سرچ، به اس کیو ال هم پاسخ میدهند. اس کیو ال و اس کیو ال با پارامتر ردیفهایی برمیگردانند که رابط ردیفهای پایگاه داده را پیاده میکنند و با فراخوانی بعدی خودشان صفحههای بعد را میآورند. اتصال عمومی(ک) کارخواه را به شکل یک اتصال پایگاه داده درمیآورد، پس تابعی که برای اس کیو لایت یا پستگرس نوشته شده میتواند از الستیک سرچ هم بخواند. این اتصال فقط خواندنی است: نوشتن با نمایه کردن، دستهای و حذف با پرسمان انجام میشود.
واردسازی دیتابیس
واردسازی دیتابیس.الستیک سرچ
تابع نویسندگان(رابط: پویا دیتابیس.اتصال):
ردیفها := رابط.پرسمان("SELECT author, COUNT(*) AS books FROM books GROUP BY author ORDER BY author")
تا ردیفها.بعدی():
سرچاپ ردیفها.متن(0)، ردیفها.عدد صحیح(1)
پایان
ردیفها.بستن()
پایان
تابع ریشه:
ناپایا ک := الستیک سرچ.اتصال("http://localhost:9200")
ناپایا پارامترها := وکتور {} برگردان وکتور<رشته>
پارامترها.بیفزا("1000")
ناپایا ردیفها := الستیک سرچ.اس کیو ال با پارامتر(ک، "SELECT title, year FROM books WHERE year > ? ORDER BY year"، پارامترها، 100)
تا ردیفها.بعدی():
سرچاپ ردیفها.متن(0)، ردیفها.عدد صحیح(1)
پایان
ردیفها.بستن()
نویسندگان(الستیک سرچ.اتصال عمومی(ک))
الستیک سرچ.بستن(ک)
پایانخطا و تلاش دوباره
فراخوانی ناموفق مقدار نگهبان خود را برمیگرداند (نادرست، -1، رشتهی خالی یا نتیجهای با ok نادرست) و کارخواه دلیلش را به خاطر میسپارد: خطا(ک) پیام را میدهد، نوع خطا(ک) نوع خطای الستیک سرچ مانند version_conflict_engine_exception را، و وضعیت(ک) وضعیت HTTP را که اگر هیچ گرهی پاسخ نداد ۰ است. با چند گره، کارخواه بینشان میچرخد، گرهی را که اتصال را نپذیرفت یک دقیقه کنار میگذارد و روی ۵۰۲، ۵۰۳ و ۵۰۴ دوباره تلاش میکند.
واردسازی دیتابیس.الستیک سرچ
تابع ریشه:
ناپایا پیکر := الستیک سرچ.پیکربندی { max_retries = 3، timeout_ms = 5000، keep_alive = درست }
پیکر.nodes.بیفزا("http://es-1:9200")
پیکر.nodes.بیفزا("http://es-2:9200")
ناپایا ک := الستیک سرچ.کارخواه تازه(پیکر)
نوشته := الستیک سرچ.ایجاد(ک، "books"، "1"، `{"title":"Shahnameh"}`)
اگر وارونه نوشته.ok:
ترابرد الستیک سرچ.نوع خطا(ک):
"version_conflict_engine_exception":
سرچاپ "already there"
بشکن
پایان
"":
سرچاپ "no node answered:"، الستیک سرچ.خطا(ک)
بشکن
پایان
وگرنه:
سرچاپ الستیک سرچ.وضعیت(ک)، الستیک سرچ.خطا(ک)
پایان
پایان
پایان
پ := الستیک سرچ.انجام(ک، "GET"، "/_cat/indices?format=json"، "")
سرچاپ پ.status، پ.body
الستیک سرچ.بستن(ک)
پایانهر چیزی که این بسته تابعی برایش ندارد با یک انجام(ک، روش، مسیر، بدنه) در دسترس است؛ وضعیت و بدنهی خام را برمیگرداند.
قدم بعدی
| نیاز | به کار ببرید |
|---|---|
| تنظیمات، نگاشت، نام مستعار و الگوی نمایه | تنظیم نگاشت، تنظیم تنظیمات، جابجایی نام مستعار، تنظیم الگوی نمایه |
| کپی کردن یک نمایه | نمایهسازی دوباره، یا شروع نمایهسازی دوباره و دریافت کار در پسزمینه |
| پاکسازی سندها هنگام ورود | تنظیم خط لوله و گزینهها { pipeline = ... } |
| گزارشها و دیگر دادههای زمانی | ایجاد جریان داده، چرخش نمایه، تنظیم سیاست چرخه عمر |
| پشتیبانگیری | تنظیم مخزن پشتیبان، ایجاد پشتیبان، بازیابی پشتیبان |
| جستجوهای طولانی | ارسال جستجوی ناهمگام و دریافت جستجوی ناهمگام |
| جستجوی برداری | نزدیکترین همسایهها در فیلد knn درخواست جستجو |
همهی تابعها، گونهها و فیلدها با نمونه در صفحهی مرجع بستهی الستیک سرچ توضیح داده شدهاند.