الصلات الذاتية في Azure Cosmos DB ل NoSQL

ينطبق على: NoSQL

في Azure Cosmos DB ل NoSQL، تكون البيانات خالية من المخطط وعادة ما تكون غير تسوية. بدلا من ضم البيانات عبر الكيانات والمجموعات، كما تفعل في قاعدة بيانات ارتباطية، تحدث الصلات داخل عنصر واحد. على وجه التحديد، يتم تحديد نطاق الصلات لهذا العنصر ولا يمكن أن تحدث عبر عناصر وحاويات متعددة.

تلميح

إذا وجدت نفسك بحاجة إلى الانضمام عبر العناصر والحاويات، ففكر في إعادة صياغة نموذج البيانات لتجنب ذلك.

الانضمام الذاتي مع عنصر واحد

لنلق نظرة على مثال على الصلة الذاتية داخل عنصر. ضع في اعتبارك حاوية بعنصر واحد. يمثل هذا العنصر منتجا بعلامات مختلفة:

[
  {
    "id": "863e778d-21c9-4e2a-a984-d31f947c665c",
    "categoryId": "e592b992-d453-42ee-a74e-0de2cc97db42",
    "name": "Teapo Surfboard (6'10\") Grape",
    "sku": "teapo-surfboard-72109",
    "tags": [
      {
        "id": "556dc4f5-1dbd-41dc-9674-fda626e5d15c",
        "slug": "tail-shape-swallow",
        "name": "Tail Shape: Swallow"
      },
      {
        "id": "ac097b9a-8a30-4fd1-8cb6-69d3388ee8a2",
        "slug": "length-inches-82",
        "name": "Length: 82 inches"
      },
      {
        "id": "ce62b524-8e96-4999-b3e1-61ae7a672e2e",
        "slug": "color-group-purple",
        "name": "Color Group: Purple"
      }
    ]
  }
]

ماذا لو كنت بحاجة إلى العثور على مجموعة ألوان هذا المنتج؟ عادة ما تحتاج إلى كتابة استعلام يحتوي على عامل تصفية يفحص كل فهرس محتمل في tags الصفيف للحصول على قيمة ببادئة .color-group-

SELECT
  * 
FROM
  products p
WHERE
  STARTSWITH(p.tags[0].slug, "color-group-") OR
  STARTSWITH(p.tags[1].slug, "color-group-") OR
  STARTSWITH(p.tags[2].slug, "color-group-")

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

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

SELECT
  p.id,
  p.sku,
  t.slug
FROM
  products p
JOIN
  t IN p.tags

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

[
  {
    "id": "863e778d-21c9-4e2a-a984-d31f947c665c",
    "sku": "teapo-surfboard-72109",
    "slug": "tail-shape-swallow"
  },
  {
    "id": "863e778d-21c9-4e2a-a984-d31f947c665c",
    "sku": "teapo-surfboard-72109",
    "slug": "length-inches-82"
  },
  {
    "id": "863e778d-21c9-4e2a-a984-d31f947c665c",
    "sku": "teapo-surfboard-72109",
    "slug": "color-group-purple"
  }
]

دعونا نقسم الاستعلام. يحتوي الاستعلام الآن على اسمين مستعارين: p لكل عنصر منتج في مجموعة النتائج، وللصفيف t المرتبط tags ذاتيا. * الكلمة الأساسية صالحة فقط لعرض جميع الحقول إذا كان يمكنها استنتاج مجموعة الإدخال، ولكن هناك الآن مجموعتا إدخال (p و t). وبسبب هذا القيد، يجب علينا تعريف الحقول التي تم إرجاعها بشكل صريح كما id ومن sku المنتج جنبا إلى جنب مع slug من العلامات. لتسهيل قراءة هذا الاستعلام وفهمه، يمكننا إسقاط id الحقل واستخدام اسم مستعار لحقل العلامة name لإعادة تسميته إلى tag.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
[
  {
    "sku": "teapo-surfboard-72109",
    "tag": "Tail Shape: Swallow"
  },
  {
    "sku": "teapo-surfboard-72109",
    "tag": "Length: 82 inches"
  },
  {
    "sku": "teapo-surfboard-72109",
    "tag": "Color Group: Purple"
  }
]

وأخيرا، يمكننا استخدام عامل تصفية للعثور على العلامة color-group-purple. نظرا لأننا استخدمنا JOIN الكلمة الأساسية، فإن عامل التصفية لدينا مرن بما يكفي للتعامل مع أي عدد متغير من العلامات.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
WHERE
  STARTSWITH(t.slug, "color-group-")
[
  {
    "sku": "teapo-surfboard-72109",
    "tag": "Color Group: Purple"
  }
]

الانضمام الذاتي لعناصر متعددة

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

[
  {
    "id": "80d62f31-9892-48e5-9b9b-5714d551b8b3",
    "categoryId": "19cd9b93-bdc5-4082-97fe-2c80c2fd77dd",
    "categoryName": "Sleeping Bags",
    "name": "Maresse Sleeping Bag (6') Ming",
    "sku": "maresse-sleeping-bag-65503",
    "tags": [
      {
        "id": "f50f3ee1-e150-4821-922b-ebe6ad82f313",
        "slug": "bag-shape-mummy",
        "name": "Bag Shape: Mummy"
      },
      {
        "id": "8564fb66-63ea-464a-872a-7598433b9479",
        "slug": "bag-insulation-down-fill",
        "name": "Bag Insulation: Down Fill"
      }
    ]
  },
  {
    "id": "6e9f51c1-6b45-440f-af5a-2abc96cd083d",
    "categoryId": "19cd9b93-bdc5-4082-97fe-2c80c2fd77dd",
    "categoryName": "Sleeping Bags",
    "name": "Vareno Sleeping Bag (6') Turmeric",
    "sku": "vareno-sleeping-bag-65508",
    "tags": [
      {
        "id": "e02502ce-367e-4fb4-940e-93d994fa6062",
        "slug": "bag-insulation-synthetic-fill",
        "name": "Bag Insulation: Synthetic Fill"
      },
      {
        "id": "c0844995-3db9-4dbb-8d9d-d2c2a6151b94",
        "slug": "color-group-yellow",
        "name": "Color Group: Yellow"
      },
      {
        "id": "f50f3ee1-e150-4821-922b-ebe6ad82f313",
        "slug": "bag-shape-mummy",
        "name": "Bag Shape: Mummy"
      }
    ]
  }
]

ماذا لو كنت بحاجة إلى العثور على كل عنصر مع شكل حقيبة مومياء ؟ يمكنك البحث عن العلامة bag-shape-mummy، ولكن ستحتاج إلى كتابة استعلام معقد يمثل سمتين لهذه العناصر:

  • تحدث العلامة bag-shape- ذات البادئة في فهارس مختلفة في كل صفيف. بالنسبة لحقيبة Vareno السكون، العلامة هي العنصر الثالث (الفهرس: 2). بالنسبة لحقيبة Maresse السكون، العلامة هي العنصر الأول (الفهرس: 0).

  • الصفيف tags لكل عنصر طول مختلف. حقيبة فارينو النوم لها اثنين من العلامات في حين أن حقيبة ماريس النوم لديها ثلاث.

هنا، JOIN الكلمة الأساسية هي أداة رائعة لإنشاء منتج مشترك للعناصر والعلامات. تنشئ الصلات منتجا كاملا متقاطعا من المجموعات المشاركة في الصلة. والنتيجة هي مجموعة من المجموعات مع كل تباديل للعنصر والقيم داخل الصفيف المستهدف.

تقوم عملية الانضمام على عينة منتجات وعلامات حقيبة النوم بإنشاء العناصر التالية:

Item العلامة
Maresse Sleeping Bag (6') Ming شكل حقيبة: مومياء
Maresse Sleeping Bag (6') Ming عزل حقيبة: تعبئة لأسفل
فارينو حقيبة النوم (6') الكركم عزل حقيبة: تعبئة اصطناعية
فارينو حقيبة النوم (6') الكركم مجموعة الألوان: أصفر
فارينو حقيبة النوم (6') الكركم شكل حقيبة: مومياء

فيما يلي استعلام SQL ومجموعة نتائج JSON لصلة تتضمن عناصر متعددة في الحاوية.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
WHERE
  p.categoryName = "Sleeping Bags"
[
  {
    "sku": "maresse-sleeping-bag-65503",
    "tag": "Bag Shape: Mummy"
  },
  {
    "sku": "maresse-sleeping-bag-65503",
    "tag": "Bag Insulation: Down Fill"
  },
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Bag Insulation: Synthetic Fill"
  },
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Color Group: Yellow"
  },
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Bag Shape: Mummy"
  }
]

تماما كما هو الحال مع العنصر الفردي، يمكنك تطبيق عامل تصفية هنا للعثور على العناصر التي تطابق علامة معينة فقط. على سبيل المثال، يبحث هذا الاستعلام عن جميع العناصر ذات العلامة المسماة bag-shape-mummy لتلبية المتطلبات الأولية المذكورة سابقا في هذا القسم.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
WHERE
  p.categoryName = "Sleeping Bags" AND
  t.slug = "bag-shape-mummy"
[
  {
    "sku": "maresse-sleeping-bag-65503",
    "tag": "Bag Shape: Mummy"
  },
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Bag Shape: Mummy"
  }
]

يمكنك أيضا تغيير عامل التصفية للحصول على مجموعة نتائج مختلفة. على سبيل المثال، يبحث هذا الاستعلام عن جميع العناصر التي تحتوي على علامة تسمى bag-insulation-synthetic-fill.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
WHERE
  p.categoryName = "Sleeping Bags" AND
  t.slug = "bag-insulation-synthetic-fill"
[
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Bag Insulation: Synthetic Fill"
  }
]