您将在下方找到电子书的摘录。 点击此处下载完整电子书。
当有人考虑在应用中使用 NoSQL 时,最常出现的问题是:“我如何组织我的数据结构?” 这个问题的简短回答是,正如您可能猜到的那样,视情况而定。 有几个问题可以帮助您确定如何在 NoSQL 数据库中组织数据结构。 您的应用是读密集型还是写密集型? 您的应用的用户体验是怎样的? 您的数据需要如何呈现给用户? 您将存储多少数据? 您需要考虑哪些性能因素? 您如何预估您的应用扩展?
这些问题只是您开始使用 NoSQL 时需要问自己的问题的一小部分。 关于 NoSQL 数据库的一个常见误解是,既然它们是“无模式”的,您就不需要担心模式。 实际上,无论您选择哪种数据库,您的模式都非常重要。 您还需要确保您选择的模式能够与您计划使用的数据库很好地扩展。
在这本电子书中,您将学习如何在 NoSQL 中进行数据建模,特别是在 Redis 的背景下。 Redis 是一个极好的数据库,可以用来演示几种 NoSQL 模式和实践。 Redis 不仅受到开发者的广泛使用和喜爱,它还是一个多模型数据库。 这意味着虽然本电子书涵盖的许多模式适用于不同类型的数据库(例如文档、图、时间序列等),但使用 Redis,您可以在单个数据库中应用所有这些模式。
读完本文后,您应该具备
我相信在某种程度上您理解 SQL 和 NoSQL 之间的区别。 SQL 是一种结构化查询语言,而 NoSQL 根据上下文可以意味着几种不同的东西。 然而,总的来说,NoSQL 中的数据建模方法与 SQL 根本不同。 在可扩展性方面也存在差异,NoSQL 更易于水平扩展。
构建应用时,您可能使用像 JavaScript、Java、C# 或其他面向对象的语言。 您的数据被表示为字符串、列表、集合、哈希、JSON 等等。 然而,如果您将数据存储在 SQL 数据库或文档数据库中,您需要将数据挤压并转换为几个表或集合。 您还需要复杂的查询(例如 SQL 查询)来获取数据。 这被称为 阻抗不匹配 ,是 NoSQL 存在的基本原因。
大型应用可能会使用其他系统进行数据存储,例如 Neo4J 用于图数据、MongoDB 用于文档数据、InfluxDB 用于时间序列等等。 使用单独的数据库将阻抗不匹配问题转变为数据库编排问题。 您必须处理到不同数据库的多个连接,以及学习使用的不同客户端库。
使用 Redis,除了基本的字符串、列表、集合和哈希等数据结构外,您还可以存储更高级的数据结构,例如用于文档的 JSON、用于二级索引的 Search、用于时间序列数据的时间序列,以及概率数据(例如排行榜)。
这减少了阻抗不匹配,因为您的数据存储在 15 种结构之一中,几乎没有或根本没有转换。 您还可以使用单个连接(或连接池)和客户端库来访问您的数据。 最终得到的是一个简化的架构,其中包含专门构建的模型,这些模型速度极快且易于管理。 因此,本电子书将使用 Redis 来解释几种 NoSQL 数据建模模式。
大多数开发者至少对 SQL 以及如何在其中进行数据建模有所了解。 这是因为 SQL 被广泛使用,并且有几本非常好的书籍,甚至完整的课程都致力于此。 NoSQL 正在快速发展并变得越来越流行。 但是考虑到当您谈论 NoSQL 时,您谈论的不仅仅是一个文档存储,还有很多内容需要涵盖。 这就是为什么在本电子书中涵盖某些 NoSQL 数据建模模式时,您也会看到在 SQL 中建模数据可能是什么样子。
当您在 SQL 中进行数据建模时,您通常关注关系,因为 SQL 适用于关系数据上的基于集合的操作。 NoSQL 没有这个约束,并且在数据建模方式上更灵活。 然而,这可能导致模式过于复杂。 在考虑 NoSQL 模式设计时,始终要考虑性能,并尽量保持简单。
那么,让我们开始吧,先看看对 SQL 开发者来说非常熟悉和重要的东西: 关系。
想象一下,您正在创建一个销售电子产品的零售应用。 让我们使用 图 1 和 图 2 作为标准零售电商应用界面的示例。 首先,您将创建一个所有电子产品的列表视图,然后是一个显示每个商品所有详细信息的详细视图。 列表视图中的每个商品与商品的详细视图(如 图 2 所示)之间存在 1 对 1 关系。 详细视图显示所有详细信息,例如多张照片、描述、制造商、尺寸、重量等等。
在关系数据库中,您可以创建一个名为 products 的表,其中每一行只包含足够的数据来显示列表视图中的信息。 然后,您可以创建另一个名为 product_details 的表,其中每一行包含其余的详细信息。 您还需要一个 product_images 表,用于存储某个商品的所有图像。 您可以在 图 3 中看到实体关系图。
图 3
图 3 描绘了 products、 product_details 和 product_images 之间的实体关系,并表示一个规范化数据模型,其中 products 表中有一个非规范化的 image 字段。 这样做的原因是避免在选择用于列表视图的商品时使用 SQL JOIN。 使用这种模型,用于获取列表视图所需数据的 SQL 查询可能类似于 代码示例 1。
SELECT
p.id, p.name, p.image, p.price, pi.url
FROM
products p
在 Redis 中,类似于关系数据库,您可以创建一个名为 products 的集合,另一个名为 product_details。 但借助 Redis JSON,您可以简单地将 product_images 和 product_details 直接嵌入到 Products 集合中来改进这一点。 然后,当您查询 Products 集合时,根据您尝试创建的视图指定所需的字段。
这将允许您轻松地将所有数据保存在一处。 这被称为 嵌入模式 ,是您在像 Redis JSON 这样的 NoSQL 文档数据库中最常见的模式之一。 代码示例 2 使用 Python 和一个名为 Redis OM(用于 Redis 的 ORM)的客户端库来建模 Products 和 ProductDetails。 请注意, ProductDetails 直接嵌入到 Products 中,因此一个商品的所有数据将存储在同一个文档中。
class ProductDetail(EmbeddedJsonModel):
description: str
manufacturer: str
dimensions: str
weight: str
images: List[str]
class Product(JsonModel):
name: str = Field(index=True)
image: str = Field(index=True)
price: int = Field(index=True)
details: Optional[ProductDetail]
代码示例 2 还展示了如何使用 Redis OM 和 Redis Search 索引字段。 这样做将 Redis 变成不仅是一个文档存储,还是一个搜索引擎,因为 Redis Search 启用了二级索引和搜索。 当您使用 Redis OM 创建模型时,它将代表您使用 Redis Search 自动管理二级索引。
使用 Redis OM,我们可以编写一个函数来检索用于列表视图的 products 列表,如 代码示例 3 所示。
async def get_product_list():
results = await connections \
.get_redis_connection() \
.execute_command(
f'FT.SEARCH {Product.Meta.index_name} * LIMIT 0 10 RETURN 3 name image price'
)
return Product.from_redis(results)
请注意,在 代码示例 3 中,我们使用了 FT.SEARCH 命令,该命令指定了 Redis OM 代表我们管理的索引,并返回三个字段:name、image 和 price。 虽然文档都嵌入了 details 和 images,但我们不想在列表视图中显示它们,所以我们不需要查询它们。 当我们需要详细视图时,我们可以查询整个 Product 文档。 请参阅 代码示例 4 了解如何查询整个文档。
async def get_product_details(product_id: str):
return await Product.get(product_id)
使用 Redis 时,您可以使用 RedisInsight 作为 GUI 工具来可视化并与数据库中的数据进行交互。 图 4 向您展示了 Products 文档是什么样子。
图 4
我相信您一定渴望了解更多,因此 点击此处下载完整电子书。