صف بإيجاز كيفية تخزين البيانات العلائقية المعقدة في ElasticSearch

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

نعلم جميعًا أن ElasticSearch عبارة عن قاعدة بيانات لنوع NoSQL ، مما يضعف من معالجة العلاقات ، لأن أطر عمل البحث عن النص الكامل مثل lucene و es و solr لها متطلبات أداء أعلى. بمجرد حدوث عملية الربط ، سيكون الأداء سيئًا للغاية ، لذلك عند استخدام إطار البحث ، يجب أن نتجنب استخدام محرك البحث كقاعدة بيانات علائقية.

بالطبع ، ترتبط البيانات الفعلية بالتأكيد ، فكيف تتعامل مع هذه البيانات العلائقية وتديرها في es؟

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

أولاً ، استخدم أنواع الحقول من الكائن والصفيف [الكائن] لتخزين بيانات json الخاصة بالهيكل متعدد الطبقات تلقائيًا.

هذه هي الآلية الافتراضية لـ es ، أي أننا لم نقم بتعيين أي مناظرة ، وقم بإدراج بيانات json معقدة مباشرةً في خادم es ، ويمكن أيضًا إدراجها بنجاح ، ويمكن أن تدعم الاسترجاع ، (يمكن القيام بذلك لأن الافتراضي هو تعيين ديناميكي ، طالما تم إدخال بنية json القياسية سيتم تحويلها تلقائيًا ، بالطبع ، يمكننا أيضًا التحكم في نوع التعيين ، es داخل التعيين الديناميكي والتعيين الثابت ، يتم تقسيم التعيين الثابت أيضًا إلى نوع صارم ، نوع ضعيف ، نوع عام ، لم يعد قم بتوسيع هنا المهتمة يمكن أن تتعلم من الموقع الرسمي) باعتبارها واحدة من البيانات التالية:

{
  "الاسم": "زاك" ،
  "سيارة"  : [
    {
      "اصنع": "زحل" ،
      "نموذج": "SL"
    }،
    {
      "تكوين": "سوبارو" ،
      "نموذج": "امبريزا"
    }
  ]
}

هيكل التخزين الناتج مشابه لما يلي:

{
  "الاسم": "زاك" ،
  "car.make": ["زحل" ، "سوبارو"]
  "car.model": ["SL" ، "Imprezza"]
}

نظرًا لأن لوسين es الأساسي هو دعم طبيعي للتخزين متعدد القيم ، يبدو كأنه بنية صفيف أعلاه. في الواقع ، يتم تخزين es في هذا الحقل كحقل متعدد القيم.

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

ثانياً ، استخدم النوع [الكائن] المتداخل لتخزين البيانات ذات العلاقات متعددة المستويات

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

نفس بيانات json:

{
  "الاسم": "زاك" ،
  "سيارة"  : [
    {
      "اصنع": "زحل" ،
      "نموذج": "SL"
    }،
    {
      "تكوين": "سوبارو" ،
      "نموذج": "امبريزا"
    }
  ]
}

في السيناريو 1 ، ستقوم es الأخيرة بتخزين جزء من البيانات ، في النوع الثاني ، وإذا تم الإعلان عن نوع السيارة المتداخلة ، فسيتم عرض رقم es المخزنة في النهائي 3 ، وضح هنا كيف سيأتي 3 = جذر واحد المستندات + 2 سيارة ، نوع الإعلان المتداخل ، كل مثيل هو مستند جديد ، لذلك يمكن الاستعلام بشكل مستقل عند الاستعلام ، والأداء ليس سيئًا ، لأن الجزء السفلي من es سيكون له نفس البيانات. العيب هو أن تكلفة التحديث كبيرة نسبيًا ، كل تحديث مستند فرعي يجب أن يعيد بناء فهرس البنية بأكملها ، بحيث يكون المتداخل مناسبًا لسيناريوهات العلاقات متعددة المستويات المتداخلة التي لا يتم تحديثها بشكل متكرر.

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

تحتوي التطبيقات المتداخلة على وضعين:

  • استعلام متداخل
    كل استعلام صالح داخل مستند واحد ، بما في ذلك الفرز
  • التجميع المتداخل أو التصفية
    جميع الوثائق من نفس المستوى صالحة عالميا ، بما في ذلك تصفية الفرز

ثالثا ، علاقة الوالدين / الأطفال

يشبه نمط الوالدين / الأطفال النمط المتداخل للغاية ، لكن تركيز التطبيق مختلف.

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

نوع مناظرة المستند الأصلي:

{
  "التعيينات": {
    "شخص" :{
      "اسم" :{
        "النوع": "السلسلة"
      }
    }
  }
}

تعيين نوع المستند الثانوي:

{
  "المنازل": {
    "_الأبوين" :{
      "النوع": "الشخص"
    }،
    "حالة"  : {
      "النوع": "السلسلة"
    }
  }
}

عند إدراج البيانات ، تحتاج إلى إدراج المستند الأصل أولاً:

حليقة -XPUT المضيف المحلي: 9200 / اختبار / شخص / زاك / -d '
{
  "الاسم": "زاك"
}

ثم عند إدراج مستند ثانوي ، تحتاج إلى إضافة حقل توجيه:

حليقة $ -XPOST مضيف محلي: 9200 / المنازل؟ الأصل = زاك -d '
{
  "الولاية": "أوهايو"
}
$ curl -XPOST localhost: 9200 / test / homes؟ parent = zach -d '
{
  "الولاية": "ساوث كارولينا"
}

لنلخص:

الطريقة الأولى:

  1. أداء بسيط وسريع وعالي
  2. جيد في الحفاظ على العلاقة الشخصية
  3. لا استفسار خاص مطلوب

الطريقة الثانية:

  1. نظرًا لأنه يتم تخزين الطبقة الأساسية في نفس sengment ، فإن طريقة مقارنة أداء القراءة والاستعلام تكون أسرع.
  2. سيؤدي تحديث مستند ثانوي واحد إلى إعادة إنشاء بنية البيانات بالكامل ، بحيث لا يناسب تحديث المشاهد المتداخلة المتكررة.
  3. يمكن الحفاظ على علاقات تخزين واحد إلى كثير والعديد من أطراف التخزين

الطريقة الثالثة:

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

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