在適用於 NoSQL 的 Azure Cosmos DB 中自我聯結
適用於:NoSQL
在適用於 NoSQL 的 Azure Cosmos DB 中,數據是無架構的,而且通常會反正規化。 如同在關係資料庫中一樣,聯結不會跨實體和集合聯結數據,而是在單一專案中發生聯結。 具體來說,聯結的範圍是該專案,而且無法在多個專案和容器之間發生。
提示
如果您發現自己需要跨專案和容器聯結,請考慮重新作業 您的數據模型 以避免這種情況。
使用單一專案自我聯結
讓我們看看專案內自我聯結的範例。 請考慮具有單一專案的容器。 此專案代表具有各種標籤的產品:
[
{
"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 的 API 中,我們可以使用 關鍵詞在專案 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-
標記會在每個數位中的不同索引發生。 對於瓦雷諾睡袋,標籤是第三個專案(索引:2
)。 對於 Maresse 睡眠袋,捲標是第一個專案(索引:0
)。tags
每個項目的陣列都是不同的長度。 瓦雷諾睡袋有兩個標籤,而馬雷塞睡袋有三個標籤。
在這裡, JOIN
關鍵詞是建立專案和標記交叉乘積的絕佳工具。 聯結會建立參與聯結之集合的完整交叉乘積。 結果是一組 Tuple,每個排列專案和目標陣列中的值。
我們範例睡眠袋產品和標籤的聯結作業會建立下列專案:
項目 | 標籤 |
---|---|
馬雷西睡袋 (6') 明 | 包形狀:木乃伊 |
馬雷西睡袋 (6') 明 | 包絕緣:向下填滿 |
瓦雷諾睡袋 (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"
}
]
相關內容
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應