我们使用 Redis 内置的 Hash 数据类型来表示用户和位置实体。Hash 非常适合这项任务,但它们的局限性在于只能包含扁平的键/值对。对于我们的位置,我们希望以更结构化的方式存储更多详细信息。
以下是我们想要存储的位置附加数据示例
{
"id": 121,
"hours": [
{ "day": "Monday", "hours": "6-7" },
{ "day": "Tuesday", "hours": "6-7" },
{ "day": "Wednesday", "hours": "7-8" },
{ "day": "Thursday", "hours": "6-9" },
{ "day": "Friday", "hours": "8-5" },
{ "day": "Saturday", "hours": "9-6" },
{ "day": "Sunday", "hours": "6-4" }
],
"socials": [
{
"instagram": "theginclub",
"facebook": "theginclub",
"twitter": "theginclub"
}
],
"website": "www.theginclub.com",
"description": "Lorem ipsum...",
"phone": "(318) 251-0608"
}
我们可以将这些数据作为序列化的 JSON 存储在 Redis String 中,但这样一来,我们的应用每次想要读取部分数据时,都必须检索和解析整个文档。更新时也必须这样做。此外,使用这种方法,更新操作不是原子的,当我们正在应用代码中修改某个键上存储的 JSON 时,第二个客户端可能会更新它。然后,当我们把我们修改过的 JSON 版本序列化回 Redis String 时,其他客户端的修改就会丢失。
Redis Stack 为 Redis 添加了一个新的 JSON 数据类型,以及用于在 Redis 服务器上原子地选择和更新 JSON 文档中单个元素的查询语法。这使得我们的应用代码更简单、更高效且更可靠。
在本练习中,您将完成一个 API 路由的代码,该路由获取表示给定位置某一天营业时间的特定对象。打开文件 src/routes/location_routes.js
,找到 /location/:locationId/hours/:day
的路由。起始代码如下所示
// EXERCISE: Get opening hours for a given day.
router.get(
'/location/:locationId/hours/:day',
[
param('locationId').isInt({ min: 1 }),
param('day').isInt({ min: 0, max: 6 }),
apiErrorReporter,
],
async (req, res) => {
/* eslint-disable no-unused-vars */
const { locationId, day } = req.params;
/* eslint-enable */
const locationDetailsKey = redis.getKeyName('locationdetails', locationId);
// TODO: Get the opening hours for a given day from
// the JSON stored at the key held in locationDetailsKey.
// You will need to provide the correct JSON path to the hours
// array and return the element held in the position specified by
// the day variable. Make sure Redis JSON returns only the day
// requested!
const jsonPath = 'TODO';
/* eslint-enable no-unused-vars */
const hoursForDay = JSON.parse(
await redisClient.call('JSON.GET', locationDetailsKey, jsonPath),
);
/* eslint-disable */
// If null response, return empty object.
res.status(200).json(hoursForDay || {});
},
);
您需要更新代码以提供正确的 JSON 路径,用 JSON 路径表达式替换“TODO”值。
查看存储在键 ncc:locationdetails:121
的 JSON,我们看到营业时间存储在一个名为 hours
的字段中的对象数组中,其中第 0 天是星期一,第 6 天是星期日
因此,您需要一个 JSON 路径查询,根据变量 day
中存储的值,从 hours
数组中获取正确的元素。
如果您使用 redis-cli,可以使用以下命令查看 JSON 文档的结构
json.get ncc:locationdetails:121 .
确保您的查询只返回请求的那一天,这样您就不必编写 Node.js 代码来过滤从 Redis 返回的值。使用 JSON 路径语法页面 帮助您构建正确的查询。
要测试您的代码,请使用以下命令启动服务器
$ npm run dev
请记住,这将允许您在不重启服务器的情况下编辑代码并尝试您的更改。
如果您的代码中有正确的 JSON 路径,访问 https://:80801/api/location/121/hours/2
应该返回
{
"day": "Wednesday",
"hours": "7-8"
}
如果您有任何问题或需要帮助,请记住我们在 Discord 上随时为您服务。
了解更多关于 JSON 的信息,请访问 https://redis.ac.cn/docs/stack/json/。
在这个视频中,Justin 使用一个有趣的墨西哥餐车例子介绍了 JSON!