Bagikan melalui


Gabungan mandiri - Bahasa kueri di Cosmos DB (di Azure dan Fabric)

Dalam bahasa kueri, data bebas skema dan biasanya dinormalisasi. Alih-alih menggabungkan data di seluruh entitas dan set, seperti yang Anda lakukan dalam database relasional, gabungan terjadi dalam satu item. Secara khusus, gabungan dilingkup ke item tersebut dan tidak dapat terjadi di beberapa item dan kontainer.

Petunjuk / Saran

Jika Anda merasa perlu bergabung di seluruh item dan kontainer, pertimbangkan untuk mengerjakan ulang model data Anda untuk menghindari anti-pola ini.

Gabungan mandiri dengan satu item

Mari kita lihat contoh gabungan mandiri dalam item. Pertimbangkan kontainer dengan satu item. Item ini mewakili produk dengan berbagai ukuran:

[
  {
    "name": "Raiot Jacket",
    "sizes": [
      {
        "key": "s",
        "description": "Small"
      },
      {
        "key": "m",
        "description": "Medium"
      },
      {
        "key": "l",
        "description": "Large"
      },
      {
        "key": "xl",
        "description": "Extra Large"
      }
    ]
  }
]

Bagaimana jika Anda perlu menemukan produk dengan ukuran tertentu? Biasanya, Anda perlu menulis kueri yang memiliki filter yang memeriksa setiap indeks potensial dalam sizes array untuk nilai dengan awalan. Dalam contoh ini, kueri menemukan semua produk dengan ukuran yang berakhiran dengan Large:

SELECT
  *
FROM
  products p
WHERE
  p.sizes[0].description LIKE "%Large" OR
  p.sizes[1].description LIKE "%Large" OR
  p.sizes[2].description LIKE "%Large" OR
  p.sizes[3].description LIKE "%Large"

Teknik ini bisa menjadi tidak dapat dipertahkan dengan cepat. Kompleksitas atau panjang sintaks kueri meningkatkan jumlah item potensial dalam array. Selain itu, kueri ini tidak cukup fleksibel untuk menangani produk di masa mendatang, yang mungkin memiliki lebih dari tiga ukuran.

Dalam database relasional tradisional, ukuran akan dipisahkan menjadi tabel terpisah dan gabungan lintas tabel dilakukan dengan filter yang diterapkan ke hasil. Dalam bahasa kueri, kita dapat melakukan operasi gabungan mandiri dalam item menggunakan JOIN kata kunci:

SELECT
  p.name,
  s.key,
  s.description
FROM
  products p
JOIN
  s in p.sizes

Kueri ini mengembalikan array sederhana dengan item untuk setiap nilai dalam array tag.

[
  {
    "name": "Raiot Jacket",
    "key": "s",
    "description": "Small"
  },
  {
    "name": "Raiot Jacket",
    "key": "m",
    "description": "Medium"
  },
  {
    "name": "Raiot Jacket",
    "key": "l",
    "description": "Large"
  },
  {
    "name": "Raiot Jacket",
    "key": "xl",
    "description": "Extra Large"
  }
]

Mari kita uraikan kueri. Kueri sekarang memiliki dua alias: p untuk setiap item produk dalam tataan hasil, dan s untuk array yang bergabung sizes sendiri. Kata * kunci hanya valid untuk memproyeksikan semua bidang jika dapat menyimpulkan set input, tetapi sekarang ada dua set input (p dan t). Karena kendala ini, kita harus secara eksplisit mendefinisikan bidang yang dikembalikan seperti name dari produk bersama dengan key, dan description dari ukuran.

Terakhir, kita dapat menggunakan filter untuk menemukan ukuran yang berakhiran dengan Large. Karena kami menggunakan JOIN kata kunci, filter kami cukup fleksibel untuk menangani jumlah variabel tag:

SELECT
  p.name,
  s.key AS size
FROM
  products p
JOIN
  s in p.sizes
WHERE
  s.description LIKE "%Large"
[
  {
    "name": "Raiot Jacket",
    "size": "l"
  },
  {
    "name": "Raiot Jacket",
    "size": "xl"
  }
]

Menggabungkan beberapa item secara mandiri

Mari kita lanjutkan ke sampel di mana kita perlu menemukan nilai dalam array yang ada di beberapa item. Untuk contoh ini, pertimbangkan kontainer dengan dua item produk. Setiap item berisi relevan colors untuk item tersebut.

[
  {
    "name": "Gremon Fins",
    "colors": [
      "science-blue",
      "turbo"
    ]
  },
  {
    "name": "Elecy Jacket",
    "colors": [
      "indigo-shark",
      "jordy-blue-shark"
    ]
  },
  {
    "name": "Tresko Pack",
    "colors": [
      "golden-dream"
    ]
  }
]

Bagaimana jika Anda perlu menemukan setiap item dengan warna yang disertakan blue dalam nama? Anda dapat mencari string bluesecara manual , tetapi Anda harus menulis kueri kompleks yang memperkirakan dua karakteristik item ini:

  • Warna dengan blue substring terjadi pada indeks yang berbeda di setiap array. Elecy Jacket Untuk produk, warnanya adalah item kedua (indeks: 1). Gremon Fins Untuk produk, tag adalah item pertama (indeks: 0). Produk Tresko Pack tidak memiliki yang berisi substring ini.

  • Array colors untuk setiap item memiliki panjang yang berbeda. Produk Gremon Fins dan Elecy Jacket keduanya memiliki dua warna sementara Tresko Pack produk hanya memiliki satu.

Di sini, JOIN kata kunci adalah alat yang bagus untuk membuat produk silang dari item dan warna. Gabungan membuat produk silang lengkap dari set yang berpartisipasi dalam gabungan. Hasilnya adalah sekumpulan tuple dengan setiap permutasi item dan nilai dalam array yang ditargetkan.

Operasi gabungan pada produk dan warna sampel kami membuat item berikut:

Produk Color
Gremon Fins science-blue
Gremon Fins turbo
Elecy Jacket indigo-shark
Elecy Jacket jordy-blue-shark
Tresko Pack golden-dream

Contoh kueri NoSQl ini menggunakan JOIN kata kunci untuk membuat lintas produk dan mengembalikan semua permutasi:

SELECT
  p.name,
  c AS color
FROM
  products p
JOIN
  c in p.colors
[
  {
    "name": "Elecy Jacket",
    "color": "indigo-shark"
  },
  {
    "name": "Elecy Jacket",
    "color": "jordy-blue-shark"
  },
  {
    "name": "Gremon Fins",
    "color": "science-blue"
  },
  {
    "name": "Gremon Fins",
    "color": "turbo"
  },
  {
    "name": "Tresko Pack",
    "color": "golden-dream"
  }
]

Sama seperti item tunggal, Anda dapat menerapkan filter di sini untuk menemukan hanya item yang cocok dengan tag tertentu. Misalnya, kueri ini menemukan semua item dengan substring yang berisi blue untuk memenuhi persyaratan awal yang disebutkan sebelumnya di bagian ini.

SELECT
  p.name,
  c AS color
FROM
  products p
JOIN
  c in p.colors
WHERE
  c LIKE "%blue%"
[
  {
    "name": "Elecy Jacket",
    "color": "jordy-blue-shark"
  },
  {
    "name": "Gremon Fins",
    "color": "science-blue"
  }
]

Kueri ini dapat disempurnakan lebih jauh untuk mengembalikan nama produk yang memenuhi filter. Contoh ini tidak memproyekan nilai warna, tetapi filter masih berfungsi seperti yang diharapkan:

SELECT VALUE
  p.name
FROM
  products p
JOIN
  c in p.colors
WHERE
  c LIKE "%blue%"
[
  "Elecy Jacket",
  "Gremon Fins"
]