共用方式為


自我聯結 - Cosmos DB 中的查詢語言 (在 Azure 和 Fabric 中)

在查詢語言中,資料是無結構描述的,而且通常是非正規化的。 聯結不是像在關聯式資料庫中那樣跨實體和集合聯結資料,而是在單一項目中進行聯結。 具體而言,聯結的範圍限定為該項目,而且無法跨多個項目和容器發生。

小提示

如果您發現自己需要跨項目和容器聯結,請考慮重新設計資料模型以避免這種反模式。

使用單一項目自行聯結

讓我們看一個項目內的自聯結範例。 考慮一個裝有單一物品的容器。 此項目代表各種尺寸的產品:

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

如果您需要尋找特定尺寸的產品怎麼辦? 一般而言,您必須撰寫具有篩選器的查詢,以檢查陣列中 sizes 每個潛在索引中是否有具有前置詞的值。 在此範例中,查詢會尋找尺寸結尾 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"

這種技術很快就會變得站不住腳。 查詢語法的複雜性或長度會增加陣列中潛在項目的數量。 此外,此查詢不夠靈活,無法處理未來的產品,這些產品可能有三種以上的大小。

在傳統的關聯式資料庫中,大小會分成個別的表格,並執行跨表格聯結,並將篩選器套用至結果。 在查詢語言中,我們可以使用關鍵字在 JOIN 項目內進行自連接操作:

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

此查詢會傳回一個簡單的陣列,其中包含標籤陣列中每個值的專案。

[
  {
    "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"
  }
]

讓我們分解一下查詢。 查詢現在有兩個別名: p 結果集中的每個產品項目,以及 s 自聯結 sizes 陣列。 關鍵字只有 * 在可以推斷輸入集時才對投影所有欄位有效,但現在有兩個輸入集(pt)。 由於此限制,我們必須明確定義傳回的欄位, name 即來自產品以及 key,以及 description 大小。

最後,我們可以使用過濾器來尋找以 結尾 Large的大小。 因為我們使用了 JOIN 關鍵字,所以我們的過濾器足夠靈活,可以處理任何可變數量的標籤:

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"
  }
]

自行聯結多個項目

讓我們繼續討論一個範例,我們需要在存在於多個項目中的數組中尋找值。 在此範例中,請考慮包含兩個產品項目的容器。 每個項目都包含與該項目相關的項目 colors

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

如果您需要找到名稱中包含 blue 顏色的每件商品怎麼辦? 您可以手動搜尋字串 blue,但您必須撰寫複雜的查詢,以考慮這些專案的兩個特性:

  • 具有子字串的 blue 顏色出現在每個陣列中的不同索引處。 對於產品, Elecy Jacket 顏色是第二項(索引: 1)。 對於 Gremon Fins 產品,標籤是第一個項目(索引: 0)。 產品 Tresko Pack 沒有任何包含此子字串的內容。

  • colors每個項目的陣列長度都不同。 和Gremon FinsElecy Jacket產品都有兩種顏色,而Tresko Pack產品只有一種顏色。

在這裡, JOIN 關鍵字是創建項目和顏色叉積的絕佳工具。 聯結會建立參與聯結的集合 的完整叉積 。 結果是一組元組,其中包含項目的每個排列和目標數組中的值。

對我們的範例產品和顏色進行聯結作業會建立下列項目:

Product 顏色
Gremon Fins science-blue
Gremon Fins turbo
Elecy Jacket indigo-shark
Elecy Jacket jordy-blue-shark
Tresko Pack golden-dream

此範例 NoSQl 查詢使用 JOIN 關鍵字來建立交叉乘積,並傳回所有排列:

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"
  }
]

就像單一項目一樣,您可以在此處套用篩選器,以僅尋找符合特定標籤的項目。 例如,此查詢會尋找子字串包含符合本節稍早提及的初始需求的所有 blue 專案。

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"
  }
]

此查詢可以進一步精簡,只傳回符合篩選條件的產品名稱。 此範例不會投影色彩值,但篩選器仍會如預期般運作:

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