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

مفاهيم لتوضيح ذلك
البحث عن نص كامل - ابحث عن المنتجات حسب الكلمة أو العبارة. بالنسبة للمستخدم ، هذا حقل لإدخال النص باستخدام الزر "بحث" ، المتاح في أي صفحة من صفحات الموقع.
بحث متعدد الأوجه - البحث عن منتج بعدة خصائص: اللون ، الحجم ، حجم الذاكرة ، السعر ، إلخ. بالنسبة للمستخدم ، فهي عبارة عن مجموعة من المرشحات. يرتبط كل مرشح بخاصية واحدة فقط والعكس صحيح. قيم عامل التصفية هي جميع القيم الممكنة للخاصية المميزة. يرى المستخدم عوامل التصفية في صفحة القسم ، والفئة ، على الصفحة مع نتائج البحث بالنص الكامل. عندما يحدد المستخدم قيمة ، يعتبر الفلتر نشطًا.
سلوك مرشح الأوجه
باختصار ، يقوم المرشح بتصفية المنتجات وتصفية خيارات التحديد في عوامل التصفية الأخرى.
مرشحات المنتجات
من السهل مع هذا. المستخدم المحدد:
- قيمة واحدة ، ترى المنتجات التي تطابق القيمة ؛
- عدة قيم في مرشح واحد ، يرى المنتجات التي تطابق واحدًا على الأقل ؛
- القيم في عدة فلاتر ، مشاهدة المنتجات التي تطابق القيمة من كل فلتر.
من حيث الجبر المنطقي: يوجد "AND" منطقي بين المرشحات ، و "OR" منطقي بين القيم في المرشح . منطق بسيط.
خيارات المرشحات في عوامل التصفية الأخرى
"حسنًا ... ما هي الخيارات الموجودة - المعروضة ، وما هي غير المخفية" - هذه هي الطريقة التي تصف بها الشركة سلوك المرشحات. تبدو منطقية. في الممارسة العملية ، تعمل على النحو التالي:
- انتقل إلى قسم الهواتف ، واطلع على عوامل التصفية حسب الخصائص: العلامة التجارية ، والقطري ، والذاكرة. يحتوي كل مرشح على قيم.
- . . 1.
- . , . , 2.
- . . , 3.
- «» . 3 ..
يعتمد عدد قيم المرشح على عدد المنتجات: فكلما زاد عدد المنتجات ذات القيم المميزة المختلفة ، زادت القيم في عامل التصفية. قام المستخدم بتقليل عدد المنتجات في التحديد للفلاتر المتبقية عند اختيار علامة تجارية. أدى ذلك إلى تحديث قوائم القيم.
يشير هذا إلى قاعدة عامة: يتم استرداد قيم المرشح من مجموعة مختارة من المنتجات التي تشكلها بقية المرشحات النشطة.
كل مرشح نشط له اختياره الخاص من المنتجات.
إذا كان لدينا مرشحات N و:
- غير نشطة ، فالعينة عامة. إنه نفس الشيء بالنسبة لجميع المرشحات ويطابق نتائج البحث ؛
- M نشط ، و M <N ، ثم عدد العينات هو M + 1 ، حيث 1 هي العينة التي يتم تطبيق جميع المرشحات النشطة عليها. هو نفسه لجميع المرشحات غير النشطة ويتزامن مع نتائج البحث ؛
- نشط M ، و N = M ، ثم عدد العينات N. لكل مرشح عينته الخاصة.
في النهاية ، عندما يحدد المستخدم قيمة مرشح الواجهة ، يحدث ما يلي:
- يتم تشكيل اختيار بحث للبضائع ؛
- يتم استرداد قيم المرشحات غير النشطة من اختيار البحث ؛
- لكل مرشح نشط ، يتم تشكيل عينة جديدة ويتم استخراج قيم جديدة من المرشحات النشطة منه.
السؤال الذي يطرح نفسه - كيف يتم تنفيذ ذلك في الممارسة؟
تنفيذ Elasticsearch (ES)
خصائص المنتج ليست عالمية ، لذلك لن تجد هنا بنية فهرس جاهزة لتخزين المنتجات أو الاستعلامات الجاهزة. بدلاً من ذلك ، ستكون هناك روابط لوثائق تشرح كيفية إنشاء الفهارس والاستعلامات "الصحيحة" بنفسك. "صحيح" - بناءً على خبرتي ومعرفتي.
أنواع مربعات النص "الصحيحة"
في ES ، نحن مهتمون بنوعين من البيانات:
- نص للبحث عن النص الكامل. لا يمكن استخدام الحقول من هذا النوع للمقارنة الدقيقة والفرز والتجميع ؛
- الكلمة الأساسية للسلاسل التي تشارك في عمليات المقارنة الدقيقة ، والفرز ، والتجميع.
يوزع ES القيم في حقل النص ويبني قاموسًا للبحث عن نص كامل. تتم فهرسة القيم الموجودة في حقل الكلمات الرئيسية على أنها مستلمة. التجميع والفرز متاحان فقط لحقول الكلمات الرئيسية.
يستخدم المستخدم الخصائص في كلتا الحالتين: في البحث عن نص كامل ومن خلال عوامل التصفية. لا يسمح لك ES بتعيين نوعين لحقل واحد ، ولكنه يقدم حلولاً أخرى:
الحقول
PUT my_index
{
«mappings»: {
«properties»: {
«some_property»: {
«type»: «text», // 1
«fields»: { // 2
«raw»: {
«type»: «keyword»
}
}
}
}
}
}
- نعلن عن خصائص المنتج كحقل من نوع النص .
- باستخدام معلمة الحقول ، قم بإنشاء حقل افتراضي تابع لنوع الكلمات الرئيسية . افتراضي ، لأنه موجود في الفهرس وليس في وصف المنتج. يقوم ES تلقائيًا بحفظ البيانات في الحقل الفرعي عند استلامها.
لذلك لكل خاصية.
في الاستعلامات الخاصة بعمليات المقارنة والفرز والتجميع الدقيقة ، يجب عليك استخدام حقل ظاهري فرعي من نوع الكلمة الأساسية . في المثال ، هذا هو some_property.raw . للبحث عن النص - الوالدين.
copy_to .
PUT my_index
{
«mappings»: {
«properties»: {
«all_properties»: { // 1
«type»: «text»
}, «some_property_1»: {
«type»: «keyword»,
«copy_to»: «all_properties» // 2
},
«some_property_2»: {
«type»: «keyword»,
«copy_to»: «all_properties»
}
}
}
- قم بإنشاء حقل افتراضي بنوع النص في الفهرس .
- قم بتعريف كل خاصية على أنها كلمة أساسية باستخدام المعلمة copy_to . حدد الحقل الظاهري بقيمة المعلمة. ينسخ ES قيمة جميع الخصائص إلى الحقل الظاهري عند حفظ المستند.
بالنسبة لعمليات المقارنة الدقيقة ، والفرز والتجميع ، تحتاج إلى استخدام الحقل المميز ، للبحث عن النص - حقل بقيم جميع الخصائص.
كلا الأسلوبين ينشئان حقولًا إضافية في الفهرس غير موجودة في بنية المستند الأصلي. لذلك ، لإنشاء استعلام ، تحتاج إلى معرفة بنية الفهرس.
أفضل خيار copy_to . بعد ذلك ، لبناء استعلام بحث عن نص كامل ، يكفي معرفة حقل واحد يحتوي على نسخة من قيم جميع الخصائص.
استفسارات
للبحث عن المنتجات
سنفترض أن بنية الفهرس هي نفسها الموجودة في المتغير copy_to . للبحث عن نص كامل في ES ، يتم استخدام بنية المطابقة ، للمقارنة مع قيم عوامل التصفية ذات الأوجه - استعلام المصطلحات . يجمع الاستعلام المنطقي بين التركيبات في استعلام واحد. سيكون شيئًا مثل هذا:
{
«query» : {
«bool»: {
«must»: {
«match»: {
«virtual_field_for_fulltext_searching»: {
«query»: «some text»
}
}
},
«filter»: {
«must»: [
{«property_1»: [ «value_1_1», …, «value_1_n»]},
…
{«property_n»: [ «value_n_1», …, «value_n_m»]}
]
}
}
}
}
query.bool.must.match
استعلام البحث عن النص الكامل الرئيسي query.bool.filter عوامل تصفية لتحسين الاستعلام الرئيسي. يجب أن يعني الداخل منطقيًا "و" بين المرشحات. مصفوفة القيم في كل مرشح هي قيمة منطقية أو.
لقيم التصفية
تعمل عبارة تجميع المصطلحات على تجميع المنتجات حسب القيمة المميزة وتحسب الكمية في كل مجموعة. هذه العملية تسمى التجميع. تكمن الصعوبة في أنه بالنسبة لكل مرشح نشط ، يجب إجراء تجميع المصطلحات على مجموعة مختارة من البضائع التي تشكلها عوامل تصفية نشطة أخرى. لعوامل التصفية غير النشطة - على التحديد الذي يطابق نتائج البحث. و مرشح تجميع بناء يسمح لك لخلق مجموعة منفصلة لكل التجميع وعمليات "حزمة" في استعلام واحد.
سيكون هيكل الطلب على النحو التالي:
{
«size»: 0,
«query» : {
«bool»: {
«must»: {
«match»: {
«field_for_fulltext_searching»: {
«fuzziness»: 2,
«query»: «some text»
}
}
},
«filter»: {
}
}
},
«aggs» : {
«inavtive_filter_agg» : {
«filter» : { …
},
«aggs»: {
«some_inavtive_filter_subagg»: {
«terms» : {
«field» : «some_property»
}
},
...
«some_other_inavtive_filter_subagg»: {
«terms» : {
«field» : «some_other_property»
}
}
}
},
«active_filter_1_agg» : {
«filter»: {
… },
«aggs»: {
«active_filter_1_subagg»: {
«terms» : {
«field»: «property_1»
}
}
}
},
…,
«active_filter_N_agg» : {
«filter»: {
…
},
«aggs»: {
«active_filter_N_subagg»: {
«terms» : {
«field»: «property_N»
}
}
}
}
}
}
query.bool - الاستعلام الرئيسي ، يتم تنفيذ عمليات التصفية في سياقه. إنها تتكون من:
- تطابق - طلب البحث عن نص كامل ؛
- المرشحات - عوامل التصفية حسب الخصائص التي لا ترتبط بمرشحات الواجهة ويجب أن تكون موجودة في أي مجموعة فرعية. يمكن أن يكون هذا مرشحًا بواسطة in_stock ، is_visible ، إذا كنت تريد دائمًا عرض المنتجات الموجودة في المخزون فقط أو المنتجات المرئية فقط.
aggs.inavtive_filter_agg - يتكون تجميع عوامل التصفية غير النشطة من:
- عامل التصفية - الشروط حسب الخصائص التي يتم تكوينها بواسطة مرشحات الوجه النشطة. جنبا إلى جنب مع الاستعلام الرئيسي ، يتم تشكيل مجموعة مختارة من البضائع ، والتي يتم إجراء التجميعات الفرعية لهذا القسم عليها ؛
- aggs هو كائن تجميع مسمى لكل مرشح غير نشط .
aggs.active_filter_1_agg - تجميع الحصول على قيم أول عوامل تصفية الوجه النشطة. كل تصميم مرتبط بفلتر وجه واحد. يتكون من:
- عامل التصفية - الشروط حسب الخصائص التي يتم تكوينها بواسطة مرشحات الوجه النشطة ، باستثناء المرشح الحالي. جنبا إلى جنب مع الاستعلام الرئيسي ، فإنه يشكل مجموعة مختارة من البضائع ، والتي يتم إجراء التجميع الفرعي لهذا القسم عليها ؛
- aggs - كائن من تجميع واحد وفقًا لخاصية مرشح الوجه النشط حاليًا.
من المهم تحديد "الحجم": 0 ، وإلا ستحصل على قائمة بالمنتجات المطابقة للاستعلام الرئيسي بدون تجميعات.
في النهاية
استقبلت طلبين:
- لنتائج البحث ، إرجاع المنتجات لعرضها على المستخدم ؛
- بالنسبة لقيم التصفية ، ينفذ التجميع ، ويعيد قيم التصفية وعدد المنتجات بهذه القيمة.
كل طلب قائم بذاته ، لذلك من الأفضل تنفيذه بشكل غير متزامن.
ملاحظة: أعترف بوجود مناهج وأدوات أكثر "صحيحة" لحل مشكلة البحث متعدد الأوجه. سأكون ممتنا لمزيد من المعلومات والأمثلة في التعليقات.