在查詢語言中,資料是無結構描述的,而且通常是非正規化的。 聯結不是像在關聯式資料庫中那樣跨實體和集合聯結資料,而是在單一項目中進行聯結。 具體而言,聯結的範圍限定為該項目,而且無法跨多個項目和容器發生。
小提示
如果您發現自己需要跨項目和容器聯結,請考慮重新設計資料模型以避免這種反模式。
使用單一項目自行聯結
讓我們看一個項目內的自聯結範例。 考慮一個裝有單一物品的容器。 此項目代表各種尺寸的產品:
[
{
"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 陣列。 關鍵字只有 * 在可以推斷輸入集時才對投影所有欄位有效,但現在有兩個輸入集(p 和 t)。 由於此限制,我們必須明確定義傳回的欄位, 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"
]