共用方式為


開始使用 JSON - Cosmos DB 中的查詢語言 (在 Azure 和 Fabric 中)

使用 JavaScript 物件表示法 (JSON) 是查詢語言的核心。 項目會儲存為 JSON,所有查詢、運算式和類型都設計為使用 JSON 資料。 如需 JSON 本身的詳細資訊,請參閱 正式的 JSON 規格

以下是在此上下文中需要了解的有關 JSON 的一些關鍵事項:

  • JSON 物件一律以 開 { 頭,結尾為 }
  • 屬性可以巢 在彼此內部。
  • 屬性值可以是陣列。
  • 屬性名稱會區分大小寫。
  • 屬性名稱可以是任何字串,即使包含空格或特殊字元。

巢狀屬性

您可以使用點表示法存取巢狀 JSON 屬性。 這就像存取大多數程式語言中的屬性一樣。

以下是具有巢狀 JSON 的範例文件:

[
  {
    "name": "Heatker Women's Jacket",
    "category": "apparel",
    "slug": "heatker-women-s-jacket",
    "sizes": [
      {
        "key": "s",
        "description": "Small"
      }
    ],
    "metadata": {
      "link": "https://www.adventure-works.com/heatker-women-s-jacket/68719520138.p"
    }
  }
]

然後,您可以在查詢中投影相同的巢狀屬性:

SELECT
  p.name,
  p.category,
  p.metadata.link
FROM
  products p
WHERE
  p.name = "Heatker Women's Jacket"

您將獲得以下預期輸出:

[
  {
    "name": "Heatker Women's Jacket",
    "category": "apparel",
    "link": "https://www.adventure-works.com/heatker-women-s-jacket/68719520138.p"
  }
]

陣列和集合

JSON 支援陣列,您可以在查詢中使用它們。 若要存取特定元素,請使用其在陣列中的位置。

使用上一節中的相同範例,我們可以使用其索引存取陣列中的項目。 例如,如果我們想存取陣列中的第一個項目,我們將使用索引 , 0 因為它是查詢語言中陣列的從 零開始的索引 系統:

SELECT
  p.name,
  p.sizes[0].description AS defaultSize
FROM
  products p
WHERE
  p.name = "Heatker Women's Jacket"

此查詢會產生下列 JSON 物件:

[
  {
    "name": "Heatker Women's Jacket",
    "defaultSize": "Small"
  }
]

現在,讓我們考慮一個具有較大陣列的範例:

[
  {
    "name": "Vencon Kid's Coat",
    "category": "apparel",
    "slug": "vencon-kid-s-coat",
    "colors": [
      "cardinal",
      "disco"
    ],
    "sizes": [
      {
        "key": "m",
        "description": "Medium"
      },
      {
        "key": "l",
        "description": "Large"
      },
      {
        "key": "xl",
        "description": "Extra Large"
      }
    ]
  }
]

通常,您想要使用子查詢或自聯結來處理陣列中的所有元素。 例如,若要將每種顏色取得為個別資料列:

SELECT
  p.name,
  c AS color
FROM
  products p
JOIN
  c IN p.colors
WHERE
  p.name = "Vencon Kid's Coat"

這將導致像這樣的 JSON 陣列:

[
  {
    "name": "Vencon Kid's Coat",
    "color": "cardinal"
  },
  {
    "name": "Vencon Kid's Coat",
    "color": "disco"
  }
]

要檢查陣列中是否存在某個值,可以在關鍵字後面 WHERE 的過濾器中使用陣列。 此範例使用 子查詢 來篩選陣列的項目:

SELECT VALUE
  p.name
FROM
  products p
WHERE
  EXISTS(SELECT VALUE
    c
  FROM
    c IN p.sizes
  WHERE
    c.description LIKE "%Large")

此查詢會產生字串的平面 JSON 陣列,其中會包含範例中的項目:

[
  ...,
  "Vencon Kid's Coat"
  ...
]

最後,可以透過組合多個屬性來建構陣列。 在此範例中,多個屬性組合成一個 metadata 陣列:

SELECT
  p.name,
  [
    p.category,
    p.slug,
    p.metadata.link
  ] AS metadata
FROM
  products p
WHERE
  p.name = "Heatker Women's Jacket"
[
  {
    "name": "Heatker Women's Jacket",
    "metadata": [
      "apparel",
      "heatker-women-s-jacket",
      "https://www.adventure-works.com/heatker-women-s-jacket/68719520138.p"
    ]
  }
]

反覆運算

查詢語言支援使用來源中的FROM關鍵字對 IN JSON 陣列進行反覆運算。

請考慮以下範例資料集:

[
  {
    "name": "Pila Swimsuit",
    "colors": [
      "regal-blue",
      "rose-bud-cherry"
    ],
    "sizes": [
      {
        "key": "m",
        "description": "Medium"
      },
      {
        "key": "l",
        "description": "Large"
      },
      {
        "key": "xl",
        "description": "Extra Large"
      }
    ]
  },
  {
    "name": "Makay Bikini",
    "colors": [
      "starship"
    ],
    "sizes": [
      {
        "key": "s",
        "description": "Small"
      },
      {
        "key": "m",
        "description": "Medium"
      },
      {
        "key": "l",
        "description": "Large"
      }
    ]
  }
]

第一個範例使用關鍵字來 IN 執行每個產品的屬性反覆 colors 運算:

SELECT
  *
FROM
  p IN p.colors
[
  "regal-blue",
  "rose-bud-cherry",
  "starship"
]

您也可以使用子句來 WHERE 過濾陣列中的個別項目。 在此範例中, sizes 會篩選屬性:

SELECT
  p.key
FROM
  p IN p.sizes
WHERE
  p.description LIKE "%Large"
[
  {
    "key": "l"
  },
  {
    "key": "xl"
  },
  {
    "key": "l"
  }
]

使用相同的 IN 關鍵字,您可以彙總陣列疊代的結果。 在此範例中,查詢會傳回容器中所有項目加總的標籤數目計數:

SELECT VALUE
  COUNT(1)
FROM
  p IN p.sizes

備註

使用 IN 關鍵字進行反覆專案時,您無法篩選或投影陣列外部的任何屬性。 相反地,您會使用 自我聯結

空值和未定義值

如果文件中不存在屬性,則其值為 undefined。 如果屬性存在,但設定為 null,則這是明確設定的值。 和undefined之間的null區別是一個重要的區別,可能會導致查詢中的混淆。

例如,此 JSON 物件的屬性值為 ,undefinedsku因為從未定義屬性:

[
  {
    "name": "Witalica helmet",
    "category": "gear",
  }
]

此 JSON 物件的值 null 會為相同屬性,因為屬性已定義,但未設定值:

[
  {
    "name": "Witalica helmet",
    "category": "gear",
    "sku": null
  }
]

有內建函數可以檢查以下情況:

  • IS_NULL 檢查屬性是否為 null
  • IS_DEFINED 檢查屬性是否存在 (不是 undefined)。

以下是檢查兩者的方法:

SELECT
  IS_DEFINED(p.sku) AS isSkuDefined,
  IS_NULL(p.sku) AS isSkuDefinedButNull
FROM
  products p

括號表示法

雖然大部分的範例都使用 表示法來指定屬性,但您一律可以使用 括弧表示 法來指定相同的屬性。

讓我們從一個簡單的物件開始,其中巢狀物件作為屬性的 metadata 值:

[
  {
    "name": "Hikomo Sandals",
    "metadata": {
      "link": "https://www.adventure-works.com/hikomo-sandals/68719519305.p"
    }
  }
]

對於該對象,我們可以使用括號表示法的組合以三種不同的方式引用metadata.link該屬性:

SELECT
  p.metadata.link AS metadataLinkDotNotation,
  p["metadata"]["link"] AS metadataLinkBracketNotation,
  p.metadata["link"] AS metadataLinkMixedNotation
FROM
  products p
WHERE
  p.name = "Hikomo Sandals"
[
  {
    "metadataLinkDotNotation": "https://www.adventure-works.com/hikomo-sandals/68719519305.p",
    "metadataLinkBracketNotation": "https://www.adventure-works.com/hikomo-sandals/68719519305.p",
    "metadataLinkMixedNotation": "https://www.adventure-works.com/hikomo-sandals/68719519305.p"
  }
]

小提示

如果屬性名稱有空格、特殊字元或符合保留字,您必須使用方括弧表示法來指定屬性。

JSON 運算式

您可以直接在查詢結果中建立 JSON 物件。 讓我們從這個 JSON 陣列作為範例開始:

[
  {
    "name": "Diannis Watch",
    "category": "apparel",
    "detailCategory": "apparel-accessories-watches",
    "slug": "diannis-watch",
    "sku": "64801",
    "price": 98,
    "quantity": 159
  },
  {
    "name": "Confira Watch",
    "category": "apparel",
    "detailCategory": "apparel-accessories-watches",
    "slug": "confira-watch",
    "sku": "64800",
    "price": 105,
    "quantity": 193
  }
]

使用最直接的語法,您可以使用尖括號 ({/}) 和 NoSQL 查詢中的內嵌 JSON 語法來影響相對扁平的 JSON 物件的屬性名稱:

SELECT {
  "brandName": p.name,
  "department": p.category
}
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-watches"
[
  {
    "$1": {
      "brandName": "Diannis Watch",
      "department": "apparel"
    }
  },
  {
    "$1": {
      "brandName": "Confira Watch",
      "department": "apparel"
    }
  }
]

在上一個範例中,結果具有推斷的名稱, $1 因為未定義明確名稱。 在下一個範例中,結果具有使用別名定義的 product 明確名稱:

SELECT {
  "brandName": p.name,
  "department": p.category
} AS product
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-watches"
[
  {
    "product": {
      "brandName": "Diannis Watch",
      "department": "apparel"
    }
  },
  {
    "product": {
      "brandName": "Confira Watch",
      "department": "apparel"
    }
  }
]

或者,可以使用陳述式中的SELECT VALUE關鍵字來VALUE展平結果:

SELECT VALUE {
  "brandName": p.name,
  "department": p.category
}
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-watches"
[
  {
    "brandName": "Diannis Watch",
    "department": "apparel"
  },
  {
    "brandName": "Confira Watch",
    "department": "apparel"
  }
]

更進一步,您可以使用 JSON 語法來「重塑」結果 JSON 物件,以包含原始專案中可能未明確定義的陣列、子物件和其他 JSON 建構。 如果用戶端應用程式預期特定結構描述中的資料與基礎資料不符,則此技術很有用。

請考慮此 JSON 結構描述,例如:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "required": [
    "id",
    "category",
    "financial"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "category": {
      "type": "object",
      "properties": {
        "department": {
          "type": "string"
        },
        "section": {
          "type": "string"
        }
      },
      "required": [
        "department"
      ]
    },
    "inventory": {
      "type": "object",
      "properties": {
        "stock": {
          "type": "number"
        }
      }
    },
    "financial": {
      "type": "object",
      "properties": {
        "listPrice": {
          "type": "number"
        }
      },
      "required": [
        "listPrice"
      ]
    }
  }
}

該結構描述將允許以以下格式結構化的 JSON 物件:

[
  {
    "id": "[string]",
    "name": "[string]",
    "category": {
      "department": "[string]",
      "section": "[string]"
    },
    "inventory": {
      "stock": [number]
    },
    "financial": {
      "listPrice": [number]
    }
  }
]

此 NoSQL 查詢會重新對應原始物件,以符合此新結構描述:

SELECT VALUE {
  "id": p.sku,
  "name": p.name,
  "category": {
    "department": p.category,
    "section": p.detailCategory
  },
  "inventory": {
    "stock": p.quantity
  },
  "financial": {
    "listPrice": p.price
  }
}
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-watches"
[
  {
    "id": "64801",
    "name": "Diannis Watch",
    "category": {
      "department": "apparel",
      "section": "apparel-accessories-watches"
    },
    "inventory": {
      "stock": 159
    },
    "financial": {
      "listPrice": 98
    }
  },
  {
    "id": "64800",
    "name": "Confira Watch",
    "category": {
      "department": "apparel",
      "section": "apparel-accessories-watches"
    },
    "inventory": {
      "stock": 193
    },
    "financial": {
      "listPrice": 105
    }
  }
]

容器別名

根據預設,關鍵字之後 FROM 使用的字詞會參考作為查詢目標的 容器 。 術語本身 不需要 與容器的名稱相符。

例如,如果容器名為 products,則這些查詢中的任何一個都可以正常工作,並且只要該容器是查詢的目標,就會引用容器products

SELECT
  products.id
FROM
  products
SELECT
  p.id
FROM
  p
SELECT
  items.id
FROM
  items
SELECT
  targetContainer.id
FROM
  targetContainer

為了讓您的 NoSQL 查詢更簡潔,通常會使用較短的名稱來別名容器名稱。 可以使用關鍵字完成 AS 別名:

SELECT
  p.id
FROM
  products AS p

查詢語言也具有速記語法,其中可以在目標容器的參考之後立即定義別名,而不使用 AS 關鍵字。 此速記在功能上等同於使用 AS 關鍵字:

SELECT
  p.id
FROM
  products p

屬性別名

您也可以使用具有相同 AS 關鍵字的別名定義來重新命名結果中的欄位。 對於接下來的幾個範例,請考慮以下範例資料:

[
  {
    "name": "Oceabelle Scarf",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "metadata": {
      "link": "https://www.adventure-works.com/oceabelle-scarf/68719522190.p"
    }
  },
  {
    "name": "Shinity Socks",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "metadata": {
      "link": "https://www.adventure-works.com/shinity-socks/68719522161.p"
    }
  },
  {
    "name": "Horric Socks",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "metadata": {
      "link": "https://www.adventure-works.com/horric-socks/68719522177.p"
    }
  }
]

在第一個範例中, metadataLink 別名用於 metadata.link 屬性的值:

SELECT
  p.name,
  p.metadata.link AS metadataLink
FROM
  products p
[
  {
    "name": "Oceabelle Scarf",
    "metadataLink": "https://www.adventure-works.com/oceabelle-scarf/68719522190.p"
  },
  {
    "name": "Shinity Socks",
    "metadataLink": "https://www.adventure-works.com/shinity-socks/68719522161.p"
  },
  {
    "name": "Horric Socks",
    "metadataLink": "https://www.adventure-works.com/horric-socks/68719522177.p"
  }
]

這很重要

您無法使用別名將值投影為具有空格、特殊字元或保留字的屬性名稱。 例如,如果您想要將值的投影變更為具有空格的屬性名稱,則必須使用 JSON 運算式

例如,

SELECT VALUE {
  "product name": p.name,
  "from": p.metadata.link,
  "detail/category": p.detailCategory
}
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-scarfs-and-socks"
[
  {
    "product name": "Oceabelle Scarf",
    "from": "https://www.adventure-works.com/oceabelle-scarf/68719522190.p",
    "detail/category": "apparel-accessories-scarfs-and-socks"
  },
  {
    "product name": "Shinity Socks",
    "from": "https://www.adventure-works.com/shinity-socks/68719522161.p",
    "detail/category": "apparel-accessories-scarfs-and-socks"
  },
  {
    "product name": "Horric Socks",
    "from": "https://www.adventure-works.com/horric-socks/68719522177.p",
    "detail/category": "apparel-accessories-scarfs-and-socks"
  }
]

如果 NoSQL 查詢有兩個具有相同名稱的屬性,請使用別名來重新命名其中一個或兩個屬性,以便在投影結果中消除歧義。

請考慮以下範例資料:

[
  {
    "name": "Oceabelle Scarf",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "sizes": [
      {
        "key": "s"
      },
      ...
    ],
    "tags": [
      ...
    ]
  },
  {
    "name": "Shinity Socks",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "sizes": [
      ...
      {
        "key": "10"
      },
      ...
    ],
    "tags": [
      ...
      {
        "key": "length"
      }
    ]
  },
  {
    "name": "Horric Socks",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "sizes": [
      ...
      {
        "key": "7"
      },
      ...
    ],
    "tags": [
      {
        "key": "fabric"
      },
      ...
    ]
  }
]

備註

在此範例資料和查詢結果中,為了簡潔起見,已移除多個屬性和值。

此 NoSQL 查詢會傳回 p.sizes[].key 跨乘積結果中的 和 p.tags[].key 屬性,但會為每個 key 屬性設定別名以避免衝突:

SELECT
  p.name,
  s.key AS sizeKey,
  t.key AS tagKey
FROM
  products p
JOIN
  s IN p.sizes
JOIN
  t in p.tags
WHERE
  p.detailCategory = "apparel-accessories-scarfs-and-socks"
[
  {
    "name": "Oceabelle Scarf",
    "sizeKey": "s",
    "tagKey": "fabric"
  },
  ...
  {
    "name": "Shinity Socks",
    "sizeKey": "10",
    "tagKey": "length"
  },
  ...
  {
    "name": "Horric Socks",
    "sizeKey": "7",
    "tagKey": "fabric"
  }
]