在 Azure Cosmos DB for NoSQL 中使用 JSON

适用范围: NoSQL

在 Azure Cosmos DB for NoSQL 中,项将存储为 JSON。 类型系统和表达式仅限于处理 JSON 类型。 有关详细信息,请参阅 JSON 规范

我们概括了介绍有关 JSON 使用的一些重要方面:

  • 始终使用大括号 {} 将 JSON 对象括起来
  • 可以将 JSON 属性彼此嵌套
  • JSON 属性值可以是数组
  • JSON 属性名称区分大小写
  • JSON 属性名称可以是任何字符串值(包括空格或不是字母的字符)

嵌套属性

可以使用点 (.) 访问器访问嵌套的 JSON。 可以在查询中使用嵌套的 JSON 属性,其方式与使用任何其他属性的方式相同。

下面是带有嵌套 JSON 的文档:

{
  "name": "Teapo rainbow surfboard",
  "manufacturer": {
    "name": "AdventureWorks"
  },
  "releaseDate": null,
  "metadata": {
    "sku": "72109",
    "colors": [
      "cruise",
      "picton-blue"
    ],
    "sizes": {
      "small": {
        "inches": 76,
        "feet": 6.33333
      },
      "large": {
        "inches": 92,
        "feet": 7.66667
      }
    }
  }
}

在这种情况下,skucolorssizes 属性都嵌套在 metadata 属性中。 name 属性也嵌套在 manufacturer 属性中。

第一个示例投影三个嵌套属性。

SELECT
    p.manufacturer.name,
    p.metadata.sku,
    p.metadata.sizes.small.inches AS size
FROM
    products p
[
  {
    "name": "AdventureWorks",
    "sku": "72109",
    "size": 76
  }
]

使用数组

除嵌套属性外,JSON 还支持数组。 使用数组时,可以通过引用数组中的特定元素的位置来访问该元素。

此示例访问位于特定位置的数组元素。

SELECT
    p.name,
    p.metadata.colors
FROM
    products p
WHERE
    p.metadata.colors[0] NOT LIKE "%orange%"
[
  {
    "name": "Teapo rainbow surfboard",
    "colors": [
      "cruise",
      "picton-blue"
    ]
  }
]

但在大多数情况下,在使用数组时,则需使用子查询自联接

例如,下面是使用潜在数组值和 交叉联接 返回多个排列的查询,

SELECT
    p.name,
    c AS color
FROM
    products p
JOIN
    c IN p.metadata.colors
[
  {
    "name": "Teapo rainbow surfboard",
    "color": "cruise"
  },
  {
    "name": "Teapo rainbow surfboard",
    "color": "picton-blue"
  }
]

作为另一个示例,查询还可以与子查询一起使用 EXISTS

SELECT VALUE
    p.name
FROM
    products p
WHERE
    EXISTS (SELECT VALUE 
        c
    FROM
        c IN p.metadata.colors
    WHERE
        c LIKE "%picton%")
[
  "Teapo rainbow surfboard"
]

Null 和未定义之间的区别

如果一个属性没有在项中定义,那么它的值为 undefined。 值为 null 的属性必须显式定义并分配 null 值。

Azure Cosmos DB for NoSQL 支持 nullundefined 属性的两个有用的类型检查系统函数:

  • IS_NULL - 检查属性值是否为 null
  • IS_DEFINED - 检查是否已定义 或 undefined 属性值。

下面是一个示例查询,用于检查容器中每个项的两个字段。

SELECT
    IS_NULL(p.releaseDate) AS isReleaseDateNull,
    IS_DEFINED(p.releaseDate) AS isReleaseDateDefined,
    IS_NULL(p.retirementDate) AS isRetirementDateNull,
    IS_DEFINED(p.retirementDate) AS isRetirementDateDefined
FROM
    products p
[
  {
    "isReleaseDateNull": true,
    "isReleaseDateDefined": true,
    "isRetirementDateNull": false,
    "isRetirementDateDefined": false
  }
]

有关常见运算符及其针对 nullundefined 值的行为的详细信息,请参阅 相等运算符和比较运算符

JSON 中的保留关键字和特殊字符

可以使用带引号的属性运算符 [] 访问属性。 例如,由于再也无法解析标识符“Families”,因此 SELECT c.grade and SELECT c["grade"] 是等效的。 此语法很适合用于转义包含空格和特殊字符的属性,或者其名称与 SQL 关键字或保留字相同的属性。

例如,下面是一个以几种不同方式引用属性的查询。

SELECT
    p.manufacturer.name AS dotNotationReference,
    p["manufacturer"]["name"] AS bracketReference,
    p.manufacturer["name"] AS mixedReference
FROM
    products p
[
  {
    "dotNotationReference": "AdventureWorks",
    "bracketReference": "AdventureWorks",
    "mixedReference": "AdventureWorks"
  }
]

JSON 表达式

查询投影支持 JSON 表达式和语法。

SELECT {
    "productName": p.name,
    "largeSizeInFeet": p.metadata.sizes.large.feet
}
FROM
    products p
[
  {
    "$1": {
      "productName": "Teapo rainbow surfboard",
      "largeSizeInFeet": 7.66667
    }
  }
]

在此示例中,SELECT 子句会创建一个 JSON 对象。 由于示例没有提供键,该子句使用隐式参数变量名 $<index-number>

此示例明确命名了相同的字段。

SELECT {
    "productName": p.name,
    "largeSizeInFeet": p.metadata.sizes.large.feet
} AS product
FROM
    products p
[
  {
    "product": {
      "productName": "Teapo rainbow surfboard",
      "largeSizeInFeet": 7.66667
    }
  }
]

或者,查询可以平展对象,以避免命名冗余字段。

SELECT VALUE {
    "productName": p.name,
    "largeSizeInFeet": p.metadata.sizes.large.feet
}
FROM
    products p
[
  {
    "productName": "Teapo rainbow surfboard",
    "largeSizeInFeet": 7.66667
  }
]

别名值

可以显式为查询中的值指定别名。 如果查询包含两个同名的属性,请使用别名来重命名其中一个或两个属性,以便可以在投影的结果中消除其歧义。

示例

用于指定别名的 AS 关键字是可选的,如以下示例所示。

SELECT
    p.name,
    p.metadata.sku AS modelNumber
FROM
    products p
[
  {
    "name": "Teapo rainbow surfboard",
    "modelNumber": "72109"
  }
]

带保留关键字或特殊字符的别名值

不能使用别名将值投影为带有空格、特殊字符或保留字的属性名称。 例如,如果要将值的投影更改为带有空格的属性名称,则可以使用 JSON 表达式

下面是一个示例:

SELECT VALUE {
    "Product's name | ": p.name,
    "Model number => ": p.metadata.sku
}
FROM
    products p
[
  {
    "Product's name | ": "Teapo rainbow surfboard",
    "Model number => ": "72109"
  }
]