إجراء بحث ذكي حقًا: دليل خطوة بخطوة

ابحث في نظام معلومات الشركة - بالفعل من هذه العبارة نفسها تتعثر في الفم. من الجيد إذا كان لديك واحدة على الإطلاق ، فلا يجب عليك حتى التفكير في تجربة مستخدم إيجابية. كيف يمكن عكس اتجاه المستخدمين الذين أفسدتهم محركات البحث وإنشاء منتج سريع ودقيق ومفهوم تمامًا؟ نحتاج أن نأخذ قطعة جيدة من Elasticsearch ، حفنة من الخدمات الذكية ونعجنها في هذا الدليل.


هناك الكثير من المقالات حول كيفية ربط البحث عن النص الكامل استنادًا إلى Elasticsearch في قاعدة البيانات الحالية. ولكن من الواضح أنه لا توجد مقالات كافية حول كيفية إجراء بحث ذكي حقًا.


في الوقت نفسه ، تحولت عبارة "البحث الذكي" نفسها إلى كلمة رنانة بالفعل وتستخدم في المكان وليس في ذلك. إذن ما الذي يجب أن يفعله محرك البحث من أجل اعتباره ذكيًا؟ في النهاية ، يمكن وصف ذلك بأنه يعطي النتيجة التي يحتاجها المستخدم بالفعل ، حتى إذا كانت هذه النتيجة لا تتوافق تمامًا مع نص الطلب. تتجه محركات البحث الشهيرة مثل Google و Yandex إلى أبعد من ذلك ولا تعثر على المعلومات التي تحتاجها فحسب ، بل تجيب مباشرةً على أسئلة المستخدم.

حسنًا ، لم نتوصل إلى قرار نهائي في الحال ، ولكن ما الذي يمكن فعله لتقريب بحث النص الكامل بشكل منتظم من البحث الذكي ؟


عناصر الذكاء


البحث الذكي - هذا هو الحال تمامًا عندما يمكن للكمية أن تدخل في الجودة ويمكن أن تشكل الكثير من الميزات الصغيرة والبسيطة إلى حد ما إحساسًا بالسحر.


  • تصحيح أخطاء المستخدم - سواء كان ذلك خطأً مطبعيًا أو تخطيطًا غير صحيح أو ربما طلبًا يحتوي على عدد صغير بشكل مثير للريبة من النتائج ، ولكنه يشبه طلبًا يوجد به مزيد من المعلومات.
  • إلى عشر دردشات البرمجة اللغوية العصبية (معالجة اللغة الطبيعية ، وليس ما فكرت فيه) - إذا قام المستخدم بإدخال العروض التجارية للعام الماضي ، فهل أراد حقًا البحث عن هذه الكلمات في نص جميع المستندات أو هل احتاج إلى عروض تجارية فقط وفي العام الماضي فقط ؟
  • توقع الإدخال استنادًا إلى طلبات البحث السابقة أو المستندات الشائعة.
  • عرض النتيجة هو تسليط الضوء المعتاد للشظية وجدت ، معلومات إضافية اعتمادا على ما كنت تبحث عنه. نظرًا لأن المقترحات التجارية كانت مطلوبة في الفقرة السابقة ، فربما يكون من المنطقي إظهار موضوع الاقتراح على الفور ومن المنظمة التي جاء منها؟
  • سهولة التنقل - القدرة على تحسين استعلام البحث باستخدام عوامل تصفية إضافية.

خلفية


هناك ECM DIRECTUM مع العديد من الوثائق فيه. تتكون الوثيقة من بطاقة تحتوي على معلومات التعريف وجسم ، والتي يمكن أن تحتوي على عدة إصدارات.


الهدف هو البحث بسرعة وسهولة عن المعلومات الموجودة في هذه المستندات بالطريقة المعتادة لمستخدم لمحركات البحث.


الفهرسة


من أجل البحث عن شيء جيد ، تحتاج إلى فهرسته جيدًا أولاً.

المستندات في ECM ليست ثابتة ، يقوم المستخدمون بتعديل النص ، وإنشاء إصدارات جديدة ، وتغيير البيانات في البطاقات يتم إنشاء مستندات جديدة باستمرار ويتم حذف المستندات القديمة أحيانًا.
للاحتفاظ بالمعلومات الحديثة في Elasticsearch ، يجب إعادة فحص المستندات باستمرار. لحسن الحظ ، ECM لديها بالفعل قائمة انتظار خاصة بها من الأحداث غير المتزامنة ، لذلك عند تغيير مستند ، فقط أضفه إلى قائمة الانتظار للفهرسة.


تعيين مستندات ECM إلى مستندات Elasticsearch


يمكن أن يحتوي نص المستند في ECM على عدة إصدارات. في Elasticsearch ، يمكن اعتبار هذا بمثابة مجموعة من الكائنات المتداخلة ، ولكن بعد ذلك يصبح من غير المريح العمل معهم - يصبح من الصعب عليك كتابة استعلامات ، عند تغيير أحد الإصدارات ، ستحتاج إلى إعادة ترتيب كل شيء ، لا يمكن تخزين إصدارات مختلفة من نفس الوثيقة في فهارس مختلفة (لماذا قد تكون هناك حاجة إلى ذلك - في القسم التالي). لذلك ، نقوم بإلغاء تسمية وثيقة واحدة من ECM إلى عدة مستندات Elasticsearch مع نفس البطاقة ولكن مع هيئات مختلفة.


بالإضافة إلى البطاقة والجسم ، تتم إضافة معلومات الخدمة المختلفة إلى وثيقة Elasticsearch ، والتي تجدر الإشارة إليها بشكل منفصل:


  • قائمة بمعرفات المجموعات والمستخدمين الذين لديهم حقوق في المستند - لعمليات البحث ذات الحقوق ؛
  • عدد المكالمات إلى المستند - لملاءمة التوليف ؛
  • وقت آخر فهرسة.

مؤشر الفهرس


نعم ، فهارس الجمع. عادةً ، لا يتم استخدام فهارس متعددة لتخزين المعلومات المتشابهة في المعنى في Elasticsearch إلا إذا كانت هذه المعلومات غير قابلة للتغيير وترتبط بنوع من الفترة الزمنية ، على سبيل المثال ، السجلات. ثم يتم إنشاء المؤشرات كل شهر / يوم أو أكثر في كثير من الأحيان اعتمادا على شدة الحمل. في حالتنا ، يمكن تغيير أي مستند ، وسيكون من الممكن تخزين كل شيء في فهرس واحد.


ولكن - يمكن أن تكون المستندات في النظام بلغات مختلفة ، وتخزين البيانات متعددة اللغات في Elasticsearch يجلب مشكلتين:


  • نابعة خطأ. بالنسبة لبعض الكلمات ، سيتم العثور على الأساس بشكل صحيح ، بالنسبة للبعض - بشكل غير صحيح (ستكون هناك كلمة أخرى في الفهرس) ، بالنسبة للبعض - لن يتم العثور على الإطلاق (سيتم انسداد الفهرس بنماذج الكلمات). بالنسبة لبعض الكلمات من لغات مختلفة ومعاني مختلفة ، سيكون الأساس هو نفسه ، ومن ثم سيتم فقد معنى الكلمة. يمكن أن يؤدي استخدام عدة محفزات جذرية في صف واحد إلى حساب إضافي للقاعدة المحسوبة بالفعل.

Stamming - إيجاد أساس الكلمة. ليس من الضروري أن يكون الجذر هو أصل الكلمة أو شكلها الطبيعي. عادةً ما يكفي عرض الكلمات ذات الصلة في إطار واحد.
Lemmatization هو نوع من النشوء الذي يعتبر الشكل العادي (المفردات) للكلمة هو الأساس.

  • تردد كلمة غير صحيح. تأخذ بعض آليات تحديد الأهمية في ES في الاعتبار تواتر الكلمات التي يتم البحث عنها في الوثيقة (كلما زادت درجة ملاءمتها) وتردد الكلمات التي تم البحث عنها في الفهرس (كلما كانت الملاءمة أقل). لذلك ، لن يكون للنشر البسيط للكلام الروسي في مستند باللغة الإنجليزية ، عندما تكون المستندات الإنجليزية في الغالب في الفهرس ، وزنًا كبيرًا ، لكن الأمر يستحق خلط المستندات الإنجليزية والروسية في الفهرس ، وسيقل الوزن.

يمكن حل المشكلة الأولى للحالة عندما تستخدم لغات مختلفة مجموعات مختلفة من الأحرف ، (تستخدم المستندات الروسية-الإنجليزية الحروف السيريلية واللاتينية) - لن يعالج مصرفي اللغة اللغوية سوى الأحرف "الخاصة بهم".


فقط لحل المشكلة الثانية ، استخدمنا النهج بفهرس منفصل لكل لغة.


من خلال الجمع بين كلا الطريقتين ، نحصل على مؤشرات اللغة ، والتي تحتوي مع ذلك على مُحللات للعديد من اللغات التي لا تتقاطع في مجموعات من الأحرف: الروسية-الإنجليزية (وبشكل منفصل الإنجليزية-الروسية) ، البولندية-الروسية ، الألمانية-الروسية ، الأوكرانية-الإنجليزية ، إلخ. .


من أجل عدم إنشاء جميع الفهارس الممكنة مقدمًا ، استخدمنا قوالب الفهرس - يتيح لك Elasticsearch تحديد قالب يحتوي على إعدادات وتعيينات ، وتحديد نمط اسم فهرس. عند محاولة فهرسة مستند إلى فهرس غير موجود ، يتطابق اسمه مع أحد أنماط القالب ، لن يتم إنشاء فهرس جديد فقط ، ولكن سيتم أيضًا تطبيق الإعدادات والتعيينات من القالب المقابل.


هيكل الفهرس


بالنسبة للفهرسة ، نستخدم محللين في آن واحد (عبر حقول متعددة): افتراضي للبحث حسب العبارة الدقيقة والمخصص لكل شيء آخر:


"ru_en_analyzer": { "filter": [ "lowercase", "russian_morphology", "english_morphology", "word_delimiter", "ru_en_stopwords" ], "char_filter": [ "yo_filter" ], "type": "custom", "tokenizer": "standard"} 

مع الفلتر الصغير ، كل شيء واضح ، سأخبرك بالباقي.


مرشحات russian_morphology و english_morphology مخصصة للتحليل الصرفي للنصوص الروسية والإنجليزية ، على التوالي. أنها ليست جزءًا من Elasticsearch ويتم تضمينها كجزء من مكون إضافي لتحليل التشكل. هذه هي lemmatizers التي تستخدم نهج المفردات في تركيبة مع بعض الاستدلال وتعمل بشكل كبير ، MUCH ، أفضل من المرشحات المضمنة للغات المقابلة.


 POST _analyze { "analyzer": "russian", "text": "   " } >>    

و:


 POST _analyze { "analyzer": "ru_en_analyzer", "text": "   " } >>    

مرشح كلمة غريب جدا. إنه ، على سبيل المثال ، يساعد على التخلص من الأخطاء المطبعية عندما لا يكون هناك مساحة بعد النقطة. نستخدم التكوين التالي:


 "word_delimiter": { "catenate_all": "true", "type": "word_delimiter", "preserve_original": "true" } 

يسمح لك yo_filter بتجاهل الفرق بين E و E:


 "yo_filter": { "type": "mapping", "mappings": [ " => ", " => " ] } 

ru_en_stopwords filter type stop - قاموس كلمات التوقف لدينا.


عملية الفهرسة


تعد محتويات المستندات في ECM ، كقاعدة عامة ، ملفات بتنسيقات Office: .docx و .pdf ، إلخ. لاستخراج النص ، يتم استخدام البرنامج المساعد-ingest-attachment مع خط الأنابيب التالي:


 { "document_version": { "processors": [ { "attachment": { "field": "content", "target_field": "attachment", "properties": [ "content", "content_length", "content_type", "language" ], "indexed_chars": -1, "ignore_failure": true } }, { "remove": { "field": "content", "ignore_failure": true } }, { "script": { "lang": "painless", "params": { "languages": ["ru", "en" ], "language_delimeter": "_" }, "source": "..." } }, { "remove": { "field": "attachment", "ignore_failure": true } } ] } } 

من المعتاد في خط الأنابيب ، تجاهل أخطاء عدم وجود نص (وهذا يحدث للمستندات المشفرة) وتحديد الفهرس الهدف بناءً على لغة النص. هذا الأخير يتم بنص غير مؤلم ، والذي سأقدمه بشكل منفصل ، لأن بسبب قيود JSON ، يجب كتابتها على سطر واحد. جنبا إلى جنب مع صعوبات التصحيح (الطريقة الموصى بها هي رمي الاستثناءات هنا وهناك) ، فإنه يتحول تماما إلى واحدة مؤلمة.


 if (ctx.attachment != null) { if (params.languages.contains(ctx.attachment.language)) ctx._index = ctx._index + params.language_delimeter + ctx.attachment.language; if (ctx.attachment.content != null) ctx.content = ctx.attachment.content; if (ctx.attachment.content_length != null) ctx.content_length = ctx.attachment.content_length; if (ctx.attachment.content_type != null) ctx.content_type = ctx.attachment.content_type; if (ctx.attachment.language != null) ctx.language = ctx.attachment.language; } 

وبالتالي ، نرسل دائمًا المستند إلى index_name . إذا لم يتم تعريف اللغة أو عدم دعمها ، فستستقر الوثيقة في هذا الفهرس ، وإلا فإنها تقع في index_name_language .


لا نقوم بتخزين النص الأصلي للملف ، ولكن يتم تمكين حقل _source ، لأن يجب تحديث المستند جزئيًا وتمييز الموجود.


إذا تم تغيير البطاقة فقط منذ آخر فهرسة ، فإننا نستخدم واجهة برمجة تطبيقات Update By Query بدون خط أنابيب لتحديثها. يتيح هذا أولاً عدم سحب نصوص المستندات التي يحتمل أن تكون ثقيلة من ECM ، وثانياً ، يسرع التحديث بشكل كبير على جانب Elasticsearch - ليس عليك استخراج نص المستندات من تنسيقات المكاتب ، التي تتطلب الكثير من الموارد.


على هذا النحو ، لا يوجد تحديث للوثيقة في Elasticsearch على الإطلاق ، تقنيًا ، عند التحديث من الفهرس ، يتم إخراج المستند القديم وتغييره وفهرسته تمامًا مرة أخرى.

ولكن إذا تغير النص ، فسيتم حذف المستند القديم وفهرسته بشكل عام. هذا يسمح للمستندات بالانتقال من فهرس لغة إلى آخر.


بحث


لتسهيل الوصف ، سأقدم لقطة شاشة للنتيجة النهائية



النص الكامل


النوع الرئيسي للاستعلام الذي لدينا هو استعلام سلسلة استعلام بسيط :


 "simple_query_string": { "fields": [ "card.d*.*_text", "card.d*.*_text.exact", "card.name^2", "card.name.exact^2", "content", "content.exact" ], "query": " ", "default_operator": "or", "analyze_wildcard": true, "minimum_should_match": "-35%", "quote_field_suffix": ".exact" } 

حيث .exact هي الحقول المفهرسة بواسطة المحلل اللغوي الافتراضي . أهمية اسم المستند أعلى مرتين من الحقول الأخرى. يتيح لك الجمع بين "default_operator": "or" و "minimum_should_match": "-35%" العثور على مستندات لا تحتوي على ما يصل إلى 35٪ من الكلمات التي تم البحث عنها.


مرادفات


بشكل عام ، يتم استخدام أجهزة تحليل مختلفة للفهرسة والبحث ، ولكن الفرق الوحيد فيها هو إضافة عامل تصفية لإضافة مرادفات إلى استعلام البحث:


 "search_analyzer": { "filter": [ "lowercase", "russian_morphology", "english_morphology", "synonym_filter", "word_delimiter", "ru_en_stopwords" ], "char_filter": [ "yo_filter" ], "tokenizer": "standard" } 

 "synonym_filter": { "type": "synonym_graph", "synonyms_path": "synonyms.txt" } 

حقوق المحاسبة


لعمليات البحث القائمة على الحقوق ، يتم تضمين الاستعلام الرئيسي في Bool Query ، مع إضافة عامل تصفية:


 "bool": { "must": [ { "simple_query_string": {...} } ], "filter": [ { "terms": { "rights": [           ] } } ] } 

كما نتذكر من قسم الفهرسة ، يحتوي الفهرس على حقل بهوية المستخدمين والمجموعات التي لها حقوق في المستند. إذا كان هناك تقاطع لهذا الحقل مع الصفيف الذي تم تمريره ، فهناك حقوق.


ضبط الملاءمة


بشكل افتراضي ، يقوم Elasticsearch بتقييم مدى ملاءمة النتائج باستخدام خوارزمية BM25 باستخدام الاستعلام ونص المستند. قررنا أن ثلاثة عوامل أخرى يجب أن تؤثر على تقييم الامتثال للنتيجة المرغوبة والفعلية:


  • وقت آخر تعديل للوثيقة - كلما كان ذلك في الماضي ، قل احتمال وجود هذه الوثيقة ؛
  • عدد المكالمات إلى المستند - كلما زادت الحاجة إلى هذا المستند ؛
  • تحتوي إصدارات نص ECM على العديد من الحالات المحتملة: قيد التطوير والتشغيل والإهمال. من المنطقي أن يكون التمثيل أكثر أهمية من الآخرين.


    يمكنك تحقيق هذا التأثير بمساعدة استعلام نقاط الوظيفة :


     "function_score": { "functions": [ { "gauss": { "modified_date": { "origin": "now", "scale": "1095d", "offset": "31d", "decay": 0.5 } } }, { "field_value_factor": { "field": "access_count", "missing": 1, "modifier": "log2p" } }, { "filter": { "term": { "life_stage_value_id": { "value": "" } } }, "weight": 1.1 } ], "query": { "bool": {...} } } 

    نتيجة لذلك ، ceteris paribus ، نحصل على الاعتماد التالي لمعدل تصنيف النتائج تقريبًا في تاريخ آخر تغيير X وعدد مرات الدخول Y:




الذكاء الخارجي


بالنسبة لجزء من وظيفة البحث الذكي ، نحتاج إلى استخلاص حقائق متنوعة من استعلام البحث: التواريخ مع تطبيقها (الإنشاء ، التعديل ، الموافقة ، إلخ) ، أسماء المنظمات ، أنواع المستندات المطلوبة ، إلخ.


من المستحسن أيضًا تصنيف الطلب في فئة معينة ، على سبيل المثال ، المستندات حسب المؤسسة ، حسب الموظف ، التنظيمية ، إلخ.


يتم تنفيذ هاتين العمليتين بواسطة وحدة ECM Intelligent Module - DIRECTUM Ario .


عملية البحث الذكية


لقد حان الوقت للتفكير بمزيد من التفصيل في آليات تنفيذ عناصر الذكاء.


تصحيح خطأ المستخدم


يتم تحديد صحة التصميم استنادًا إلى نموذج اللغة trigram - بالنسبة للخط ، يتم حساب مدى احتمال مواجهته لتسلسلات الأحرف الثلاثة في النصوص باللغتين الإنجليزية والروسية. إذا كان التصميم الحالي أقل احتمالًا ، فسيتم أولاً عرض تلميح بالتخطيط الصحيح:



وثانيا ، يتم تنفيذ الخطوات الإضافية للبحث بالتخطيط الصحيح:



وإذا تعذر العثور على أي شيء بالتخطيط الصحيح ، فسيبدأ البحث بالسطر الأصلي.


يتم تنفيذ تصحيح الأخطاء المطبعية باستخدام Phrase Suggester . هناك مشكلة في ذلك - إذا قمت بتنفيذ استعلام على العديد من الفهارس في نفس الوقت ، فيمكنك اقتراح عدم إرجاع أي شيء ، بينما إذا قمت بالتنفيذ على فهرس واحد فقط ، فهناك نتائج. يتم التعامل مع ذلك عن طريق تعيين الثقة = 0 ، ولكن يقترح بعد ذلك استبدال الكلمات بشكلها العادي. موافق ، سيكون غريباً عند البحث عن "letter a " للحصول على إجابة بروح: ربما كنت تبحث عن خطاب حول ؟


يمكن التحايل على ذلك باستخدام مطالبتين في الطلب:


 "suggest": { "content_suggest": { "text": " ", "phrase": { "collate": { "query": {         {{suggestion}} } }, } }, "check_suggest": { "text": "", "phrase": { "collate": { "query": {         {{suggestion}} - ({{source_query}}) }, "params": { "source_query": " " } }, } } } 

من المعلمات الشائعة المستخدمة


 "confidence": 0.0, "max_errors": 3.0, "size": 1 

إذا قام المتظاهر الأول بإرجاع النتيجة ، لكن الثاني لم يرد ، فهذه النتيجة هي السلسلة الأصلية نفسها ، ربما بالكلمات بأشكال أخرى ، وليس هناك حاجة لإظهار تلميح. إذا كان التلميح لا يزال مطلوبًا ، يتم دمج عبارة البحث الأصلية مع التلميح. يحدث هذا عن طريق استبدال الكلمات المصححة فقط والكلمات التي يعتبرها المدقق الإملائي (باستخدام Hunspell) غير صحيحة.


إذا أعطى البحث في السلسلة المصدر 0 نتائج ، فسيتم استبداله بالسلسلة التي تم الحصول عليها بواسطة الدمج ويتم إجراء البحث مرة أخرى:



خلاف ذلك ، يتم إرجاع سلسلة المطالبة الناتجة فقط كمطالبة للبحث:



تصنيف الاستعلام واستخراج الحقائق


كما ذكرت ، نستخدم DIRECTUM Ario ، وهي خدمة تصنيف النص وخدمة استخراج الحقائق. للقيام بذلك ، قدمنا ​​للمحللين استعلامات بحث مجهولة وقائمة من الحقائق التي نهتم بها. استنادًا إلى الاستعلامات ومعرفة المستندات الموجودة في النظام ، حدد المحللون فئات متعددة ودربوا خدمة التصنيف لتحديد الفئة وفقًا لنص الاستعلام. استنادًا إلى الفئات الناتجة وقائمة الحقائق ، قمنا بصياغة قواعد استخدام هذه الحقائق. على سبيل المثال ، تعتبر العبارة الخاصة بالعام الماضي في الفئة Everyone تاريخ إنشاء المستند ، وفي الفئة حسب المؤسسة - تاريخ التسجيل. في الوقت نفسه ، يجب أن تقع تلك التي تم إنشاؤها في العام الماضي في أي فئة في تاريخ الإنشاء.


من جانب البحث - قاموا بإنشاء تكوين قاموا فيه بتسجيل الفئات ، وأي حقائق يتم تطبيقها على أي عوامل تصفية للوجه.


الانتهاء من المدخلات


بالإضافة إلى تصحيحات التخطيط المذكورة بالفعل ، تقع عمليات البحث السابقة للمستخدم والوثائق العامة في الإكمال التلقائي.



يتم تنفيذها باستخدام نوع آخر من Suggester - إكمال Suggester ، ولكن لكل منها الفروق الدقيقة الخاصة به.


الإكمال التلقائي: سجل البحث

هناك عدد أقل بكثير من المستخدمين في ECM من محركات البحث ، وتخصيص استفسارات شائعة كافية لهم لماذا لينين الفطر غير ممكن إظهار كل شيء على التوالي لا يستحق أيضًا نظرًا لاعتبارات الخصوصية. يمكن لمصطلح إكمال الإعادة المعتاد أن يبحث فقط في مجموعة المستندات بأكملها في الفهرس ، ولكن يأتي سياق الإقتحام في الإنقاذ - طريقة لتعيين سياق لكل تلميح وتصفية حسب هذه السياقات. إذا تم استخدام أسماء المستخدمين كسياقات ، فيمكن فقط عرض تاريخه للجميع.


تحتاج أيضًا إلى منح المستخدم الفرصة لإزالة المطالبة التي يشعر بالخجل. كمفتاح للحذف ، استخدمنا اسم المستخدم ونص تلميح الأدوات. نتيجة لذلك ، بالنسبة للفهرس الذي يحتوي على تلميحات ، حصلنا على مثل هذا التعيين المكرر قليلاً:


 "mappings": { "document": { "properties": { "input": { "type": "keyword" }, "suggest": { "type": "completion", "analyzer": "simple", "preserve_separators": true, "preserve_position_increments": true, "max_input_length": 50, "contexts": [ { "name": "user", "type": "CATEGORY" } ] }, "user": { "type": "keyword" } } } } 

يتم تعيين وزن كل تلميح جديد على واحد ويزيد في كل مرة تقوم فيها بإعادة إدخاله باستخدام واجهة برمجة تطبيقات Update By Query باستخدام ctx._source.suggest.weight++ النصي البسيط للغاية.


الإكمال التلقائي: المستندات

ولكن يمكن أن يكون هناك الكثير من الوثائق ومجموعات ممكنة من الحقوق. لذلك ، هنا ، على العكس من ذلك ، قررنا عدم إجراء التصفية حسب الحقوق عند الإكمال التلقائي ، ولكن فقط فهرسة المستندات العامة. نعم ، ولا تحتاج إلى إزالة النصائح الفردية من هذا الفهرس. يبدو أن التنفيذ في كل شيء أسهل من السابق ، إن لم يكن لنقطتين:


أول واحد - إكمال Suggester يدعم فقط بحث البادئة ، ويحب العملاء تعيين أرقام العناصر إلى كل شيء ، وبعض .01.01 أثناء كتابة استعلام لا .01.01 . هنا ، إلى جانب الاسم الكامل ، يمكنك أيضًا فهرسة n-grams المشتقة منه:


 { "extension": "pdf", "name": ".01.01   ", "suggest": [ { "input": "", "weight": 70 }, { "input": " ", "weight": 80 }, { "input": "  ", "weight": 90 }, { "input": ".01.01   ", "weight": 100 } ] } 

لم يكن هذا أمرًا بالغ الأهمية في القصة ، ولكن المستخدم نفسه يدخل في نفس السطر تقريبًا إذا بحث عن شيء آخر. ربما



الثاني - افتراضيًا ، جميع النصائح متساوية ، لكننا نود أن نجعل بعضها أكثر مساواة ويفضل أن يكون ذلك متسقًا مع ترتيب نتائج البحث. للقيام بذلك ، كرر تقريبًا دالات gauss و field_value_factor المستخدمة في استعلام الدرجات الوظيفية .


اتضح هنا هو مثل هذا الخط:


 { "dir_public_documents_pipeline": { "processors": [ ... { "set": { "field": "terms_array", "value": "{{name}}" } }, { "split": { "field": "terms_array", "separator": "\\s+|$" } }, { "script": { "source": "..." } } ] } } 

بالنص التالي:


 Date modified = new Date(0); if (ctx.modified_date != null) modified = new SimpleDateFormat('dd.MM.yyyy').parse(ctx.modified_date); long dayCount = (System.currentTimeMillis() - modified.getTime())/(1000*60*60*24); double score = Math.exp((-0.7*Math.max(0, dayCount - 31))/1095) * Math.log10(ctx.access_count + 2); int count = ctx.terms_array.length; ctx.suggest = new ArrayList(); ctx.suggest.add([ 'input': ctx.terms_array[count - 1], 'weight': Math.round(score * (255 - count + 1)) ]); for (int i = count - 2; i >= 0 ; --i) { if (ctx.terms_array[i].trim() != "") { ctx.suggest.add([ "input": ctx.terms_array[i] + " " + ctx.suggest[ctx.suggest.length - 1].input, "weight": Math.round(score * (255 - i))]); } } ctx.remove('terms_array'); ctx.remove('access_count'); ctx.remove('modified_date'); 

لماذا تهتم بخط أنابيب غير مؤلم بدلاً من كتابته بلغة أكثر ملاءمة؟ لأنه الآن ، باستخدام Reindex API ، يمكنك تجاوز محتويات فهارس البحث في فهارس للتلميحات (عن طريق تحديد الحقول الضرورية فقط ، بالطبع) في أمر واحد فقط.


غالبًا ما لا يتم تحديث تكوين المستندات العامة المطلوبة حقًا ، لذلك يمكن ترك هذا الأمر في بداية التشغيل اليدوي.


عرض النتائج


فئة


تحدد الفئة الأوجه التي ستكون متاحة وما سيبدو المقتطف. يمكن اكتشافه تلقائيًا عن طريق المخابرات الخارجية أو تحديده يدويًا أعلى شريط البحث.


جوانب


تعتبر الأوجه أمرًا بديهيًا لكل شخص يتم وصف سلوكه ، مع ذلك ، بقواعد غير تافهة للغاية. هؤلاء قليل منهم:


  1. تعتمد قيم الواجهة على نتائج البحث ، ولكن تعتمد نتائج البحث على الجوانب المحددة. كيفية تجنب العودية؟


  2. لا يؤثر تحديد القيم في جانب واحد على القيم الأخرى لهذا الوجه ، ولكنه يؤثر على القيم في الجوانب الأخرى:




  1. يجب ألا تختفي قيم الوجوه المحددة من قِبل المستخدم ، حتى إذا أهلكها أحد الأوجه في 0 إلى الصفر أو لم تعد موجودة في الأعلى:


في المرونة ، تتحقق الجوانب من خلال آلية التجميع ، ولكن من أجل الامتثال للقواعد الموصوفة ، يجب استثمار هذه المجموعات في بعضها البعض وتصفيتها من قبل بعضها البعض.



النظر في شظايا الطلب المسؤول عن هذا:


كود كبير جدا
 { ... "post_filter": { "bool": { "must": [ { "terms": { "card.author_value_id": [ "1951063" ] } }, { "terms": { "editor_value_id": [ "2337706", "300643" ] } } ] } }, "query": {...} "aggs": { "card.author_value_id": { "filter": { "terms": { "editor_value_id": [ "2337706", "300643" ] } }, "aggs": { "card.author_value_id": { "terms": { "field": "card.author_value_id", "size": 11, "exclude": [ "1951063" ], "missing": "" } }, "card.author_value_id_selected": { "terms": { "field": "card.author_value_id", "size": 1, "include": [ "1951063" ], "missing": "" } } } }, ... "editor_value_id": { "filter": { "terms": { "card.author_value_id": [ "1951063" ] } }, "aggs": { "editor_value_id": { "terms": { "field": "editor_value_id", "size": 11, "exclude": [ "2337706", "300643" ], "missing": "" } }, "editor_value_id_selected": { "terms": { "field": "editor_value_id", "size": 2, "include": [ "2337706", "300643" ], "missing": "" } } } }, ... } } 

ما هو هنا ما يلي:


  • يتيح لك post_filter فرض شرط إضافي على نتائج استعلام مكتمل بالفعل ولا يؤثر على نتائج المجموعات. نفس الفجوة العودية. يشمل جميع القيم المحددة لجميع الجوانب.
  • مجموعات المستوى الأعلى ، في المثال card.author_value_id و editor_value_id . لكل منها:
    • تصفية حسب قيم جميع الجوانب الأخرى ، باستثناء الخاصة بك ؛
    • تجميع متداخل لقيم الوجوه المحددة - الحماية ضد الإبادة ؛
    • التجميع المتداخل لقيم الواجهة الأخرى. نعرض أفضل 10 ، ونطلب أعلى 11 - لتحديد ما إذا كان سيتم عرض زر إظهار الكل .

قصاصات


اعتمادًا على الفئة المحددة ، قد يبدو المقتطف مختلفًا ، على سبيل المثال ، المستند نفسه عند البحث في فئة


الكل :



و الموظفين :



أو تذكر ، أردنا أن نرى موضوع العرض التجاري ومن الذي جاء منه؟



من أجل عدم سحب البطاقة بالكامل من المرونة (يؤدي هذا إلى إبطاء البحث) ، يتم استخدام تصفية المصدر :


 { ... "_source": { "includes": [ "id", "card.name", "card.card_type_value_id", "card.life_stage_value_id", "extension", ... ] }, "query": {...} ... } 

لتسليط الضوء على الكلمات الموجودة في نص المستند ، يتم استخدام أداة تمييز Fast Vector highlight - لتوليد المقتطفات الأنسب للنصوص الكبيرة والاسم - أداة التمييز المميزة الموحدة - باعتبارها الأقل تطلبًا على الموارد وهيكل الفهرس:


 "highlight": { "pre_tags": [ "<strong>" ], "post_tags": [ "</strong>" ], "encoder": "html", "fields": { "card.name": { "number_of_fragments": 0 }, "content": { "fragment_size": 300, "number_of_fragments": 3, "type": "fvh" } } }, 

في هذه الحالة ، يتم تمييز الاسم بالكامل ، ومن النص نحصل على 3 أجزاء بطول 300 حرف. يتم ضغط النص الذي تم إرجاعه بواسطة أداة تمييز Fast Vector بواسطة خوارزمية مؤقتة للحصول على حالة مقتطف.


انهيار


من الناحية التاريخية ، يتم استخدام مستخدمي ECM لحقيقة أن البحث يعيد المستندات إليهم ، ولكن في الحقيقة يبحث Elasticsearch بين إصدارات المستندات . قد يتضح أنه سيتم العثور على عدة إصدارات متطابقة تقريبًا في نفس الاستعلام. سيؤدي هذا إلى تشويش النتائج وإرباك المستخدم. لحسن الحظ ، يمكن تجنب هذا السلوك باستخدام آلية طي الحقول - بعض الإصدارات خفيفة الوزن من المجموعات التي تعمل بالفعل على النتائج النهائية (في هذا يشبه post_filter ، عكازان هما زوج ). سينتج عن الانهيار الأكثر صلة بالكائنات المنهارة.


 { ... "query": {...} ... "collapse": { "field": "id" } } 

لسوء الحظ ، للإنهيار عدد من الآثار غير السارة ، على سبيل المثال ، تستمر الخصائص العددية المختلفة لنتيجة البحث في العودة كما لو لم يكن هناك أي انهيار. وهذا يعني ، عدد النتائج ، وعدد قيم الواجهة - ستكون جميعها غير صحيحة قليلاً ، لكن المستخدم عادةً لا يلاحظ ذلك ، كما يفعل القارئ المتعب ، الذي من غير المحتمل أن يكون قد قرأ هذا الاقتراح من قبل.


النهاية.

Source: https://habr.com/ru/post/ar460263/


All Articles