Skip to content

Commit fe925ff

Browse files
committed
adding nosql data modeling e-book
1 parent b8b4ae6 commit fe925ff

File tree

9 files changed

+238
-0
lines changed

9 files changed

+238
-0
lines changed
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
---
2+
id: index-ebook-8-data-modeling-patterns
3+
title: Learn 8 NoSQL Data Modeling Patterns in Redis
4+
image: /img/ebooks/nosql-data-modeling-patterns/8-data-modeling-patterns-in-redis.jpg
5+
sidebar_label: NoSQL Data Modeling Patterns
6+
slug: /ebooks/8-nosql-data-modeling-patterns
7+
editUrl: false
8+
showLastUpdateTime: false
9+
---
10+
11+
import Excerpt from '@theme/Excerpt';
12+
13+
<Excerpt cta="https://redis.com/docs/8-data-modeling-patterns-in-redis/" image={frontMatter.image} title={frontMatter.title}>
14+
15+
## Introduction
16+
17+
When someone is looking to use NoSQL for an application, the question that most often comes up is, “How do I structure
18+
my data?” The short answer to this question is, as you might guess, it depends. There are several questions that can
19+
inform how to structure your data in a NoSQL database.
20+
Is your application read heavy, or write heavy? What does the user experience of your application look like? How does
21+
your data need to be presented to the user? How much data will you be storing? What performance considerations do
22+
you need to account for? How do you anticipate scaling your application?
23+
24+
These questions are only a small subset of what you need to ask yourself when you start working with NoSQL. A common
25+
misconception with NoSQL databases is that since they are “schemaless” you don’t need to worry about your schema.
26+
In reality, your schema is incredibly important regardless of what database you choose. You also need to ensure that the
27+
schema you choose will scale well with the database you plan to use.
28+
29+
In this e-book you will learn how to approach data modeling in NoSQL, specifically within the context of Redis. Redis is a
30+
great database for demonstrating several NoSQL patterns and practices. Not only is Redis commonly used and loved by
31+
developers, it also is a multi-model database. This means that while many of the patterns covered in this e-book apply to
32+
different types of databases (e.g. document, graph, time series, etc.), with Redis you can apply all of the patterns in
33+
a single database.
34+
35+
:::note
36+
37+
By the end of this, you should have
38+
39+
- A firm understanding of how to approach modeling data in Redis as well as in NoSQL generally.
40+
- An understanding of several NoSQL data modeling patterns, their pros and cons, as well as use cases for
41+
them in practice.
42+
- A working knowledge of how to actually write code (with examples) to take advantage of NoSQL patterns
43+
within Redis.
44+
45+
:::
46+
47+
## SQL versus NoSQL
48+
49+
I’m sure at a certain level you understand the difference between SQL and NoSQL. SQL is a structured query language
50+
whereas NoSQL can mean several different things depending on the context. However, generally speaking, the approach
51+
to modeling data is fundamentally different in NoSQL than in SQL. There are also differences in terms of scalability, with
52+
NoSQL being easier to scale horizontally.
53+
54+
When building applications you are probably using an object-oriented language like JavaScript, Java, C#, or others.
55+
Your data is represented as strings, lists, sets, hashes, JSON, and so on. However, if you store data in a SQL database
56+
or a document database, you need to squeeze and transform the data into several tables or collections. You also need
57+
complex queries (such as SQL queries) to get the data out. This is called **impedance mismatch** and is the fundamental
58+
reason why NoSQL exists.
59+
60+
A large application might use other systems for data storage such as Neo4J for graph data, MongoDB for document
61+
data, InfluxDB for time series, etc. Using separate databases turns an impedance mismatch problem into a database
62+
orchestration problem. You have to juggle multiple connections to different databases, as well as learn the different client
63+
libraries used.
64+
65+
With Redis, in addition to the basic data structures such as strings, lists, sets, and hashes, you can also store advanced
66+
data structures such as RedisJSON for documents, RediSearch for secondary indexing, RedisGraph for graph data,
67+
RedisTimeSeries for time-series data, and RedisBloom for probabilistic data (think leaderboards).
68+
69+
This reduces impedance mismatch because your data is stored in one of 15 structures with little or no transformations.
70+
You can also use a single connection (or connection pool) and client library to access your data. What you end up with is
71+
a simplified architecture with purpose-built models that are blazing fast and simple to manage. For this reason, this e-book
72+
will use Redis to explain several of the NoSQL data modeling patterns.
73+
74+
Most developers have at least a little understanding of SQL and how to model data in it. This is because SQL is widely
75+
used and there are several incredible books and even full courses devoted to it. NoSQL is quickly growing and becoming
76+
more popular. But given that when you’re talking about NoSQL you’re talking about more than just a document store, there
77+
is a lot of ground to cover. That’s why when covering certain NoSQL data modeling patterns in this e-book, you will be
78+
presented with what it might look like to model the data in SQL as well.
79+
80+
When you approach data modeling in SQL you are typically focused on relationships, as SQL is meant for set-based
81+
operations on relational data. NoSQL doesn’t have this constraint and is more flexible in the way you model data.
82+
However, this can lead to schemas that are overly complex. When considering NoSQL schema design, always think about
83+
performance and try to keep things simple.
84+
85+
So to kick things off, let’s start by looking at something that is very near and dear to a SQL developer’s heart: **relationships**.
86+
87+
## Modeling 1-to-1 Relationships
88+
89+
Imagine that you are creating a retail app that sells electronics. Let’s use **Picture 1** and **Picture 2** as an example of the
90+
UI for a standard retail e-commerce app. First, you’ll create a list view of all the electronics and then a detailed view
91+
that shows all the details of each item. There is a 1-to-1 relationship between each item in the list view and the detailed
92+
view (shown in **Picture 2**) of the item. The detailed view shows all the details such as multiple photos, description,
93+
manufacturer, dimensions, weight, and so on.
94+
95+
<div className="container">
96+
<div className="row">
97+
<div className="col col--6">
98+
<strong>Picture 1</strong>
99+
<img
100+
src="/img/ebooks/nosql-data-modeling-patterns/1-to-1-list-view.png"
101+
alt="Picture 1 1-to-1 List View"
102+
title="Picture 1 1-to-1 List View"
103+
/>
104+
</div>
105+
<div className="col col--6">
106+
<strong>Picture 2</strong>
107+
<img
108+
src="/img/ebooks/nosql-data-modeling-patterns/1-to-1-detail-view.png"
109+
alt="Picture 2 1-to-1 Detailed View"
110+
title="Picture 2 1-to-1 Detailed View"
111+
/>
112+
</div>
113+
</div>
114+
</div>
115+
116+
### 1-to-1 Relationships using SQL
117+
118+
In a relational database, you may create a table called `products` where each row holds just enough data to display the information in the list view. Then, you may create another table called `product_details` where each row holds the rest of the details. You would also need a `product_images` table, where you store all of the images for a product. You can see the entity relationship diagram in **Picture 3**.
119+
120+
<strong>Picture 3</strong>
121+
<img
122+
src="/img/ebooks/nosql-data-modeling-patterns/1-to-1-entity-diagram.png"
123+
alt="Picture 3 1-to-1 Entity Diagram"
124+
title="Picture 3 1-to-1 Entity Diagram"
125+
/>
126+
127+
Picture 3 depicts the entity relationships between `products`, `product_details`, and `product_images` and represents a normalized data model with a single denormalized field image in the `products` table. The reason for this is to avoid having to use a SQL JOIN when selecting the products for the list view. Using this model, the SQL query used to get the data needed for the list view might resemble **Code Example 1**.
128+
129+
```sql title="Code Example 1"
130+
SELECT
131+
p.id, p.name, p.image, p.price, pi.url
132+
FROM
133+
products p
134+
```
135+
136+
### 1-to-1 Relationships using Redis
137+
138+
In Redis, similar to a relational database, you can create a collection called `products` and another called `product_details`. But with RedisJSON you can improve this by simply embedding `product_images` and `product_details` directly into the `Products` collection. Then, when you query the `Products` collection, specify which fields you need based on which view you are trying to create.
139+
140+
This will allow you to easily keep all the data in one place. This is called the **Embedded Pattern** and is one of the most common patterns you will see in NoSQL document databases like RedisJSON. **Code Example 2** uses Python and a client library called Redis OM (an ORM for Redis) to model `Products` and `ProductDetails`. Note that `ProductDetails` is embedded into `Products` directly, so all of the data for a product will be stored within the same document.
141+
142+
```python title="Code Example 2"
143+
class ProductDetail(EmbeddedJsonModel):
144+
description: str
145+
manufacturer: str
146+
dimensions: str
147+
weight: str
148+
images: List[str]
149+
150+
class Product(JsonModel):
151+
name: str = Field(index=True)
152+
image: str = Field(index=True)
153+
price: int = Field(index=True)
154+
details: Optional[ProductDetail]
155+
```
156+
157+
**Code Example 2** also shows how you can index fields using Redis OM and RediSearch. Doing this turns Redis into not only a document store but also a search engine since RediSearch enables secondary indexing and searching. When you create models using Redis OM, it will automatically manage secondary indexes with RediSearch on your behalf.
158+
159+
Using Redis OM we can write a function to retrieve our `products` list for the list view, as shown in **Code Example 3**.
160+
161+
```python title="Code Example 3"
162+
async def get_product_list():
163+
results = await connections \
164+
.get_redis_connection() \
165+
.execute_command(
166+
f'FT.SEARCH {Product.Meta.index_name} * LIMIT 0 10 RETURN 3 name image price'
167+
)
168+
return Product.from_redis(results)
169+
```
170+
171+
Notice that in **Code Example 3** we are using the `FT.SEARCH` (RediSearch) command, which specifies the index managed on our behalf by Redis OM and returns three fields: name, image, and price. While the documents all have details and images embedded, we don’t want to display them in the list view so we don’t need to query them. When we want the detailed view, we can query an entire Product document. See **Code Example 4** for how to query an entire document.
172+
173+
```python title="Code Example 4"
174+
async def get_product_details(product_id: str):
175+
eturn await Product.get(product_id)
176+
```
177+
178+
When using Redis, you can use RedisInsight as a GUI tool to visualize and interact with the data in your database. **Picture 4** shows you what a `Products` document looks like.
179+
180+
<strong>Picture 4</strong>
181+
<img
182+
src="/img/ebooks/nosql-data-modeling-patterns/1-to-1-redisinsight.png"
183+
alt="Picture 4 1-to-1 RedisInsight"
184+
title="Picture 4 1-to-1 RedisInsight"
185+
/>
186+
187+
## Download the E-book
188+
189+
</Excerpt>

docusaurus.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ module.exports = {
194194
'rust',
195195
'elixir',
196196
'groovy',
197+
'sql'
197198
],
198199
},
199200

sidebars.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,5 +583,15 @@ module.exports = {
583583
'get-involved/devcember/index-devcember',
584584
],
585585
},
586+
{
587+
type: 'category',
588+
label: 'E-books',
589+
items: [
590+
{
591+
type: 'autogenerated',
592+
dirName: 'ebooks',
593+
},
594+
],
595+
},
586596
],
587597
};

src/theme/Excerpt/index.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React from 'react';
2+
3+
export interface ExcerptProps {
4+
cta: string;
5+
image: string;
6+
title: string;
7+
}
8+
9+
function Excerpt({
10+
cta,
11+
image,
12+
title,
13+
children,
14+
}: React.PropsWithChildren<ExcerptProps>): JSX.Element {
15+
return (
16+
<>
17+
<p>
18+
Below you will find an excerpt from the e-book.{' '}
19+
<a href={cta} target="_blank">
20+
Click here to download the full e-book.
21+
</a>
22+
</p>
23+
<div className="margin-bottom--xs">
24+
<img src={image} loading="lazy" alt={title} />
25+
</div>
26+
{children}
27+
28+
<p>
29+
I’m sure you’re eager to learn more, so{' '}
30+
<a href={cta} target="_blank">
31+
click here to download the full e-book.
32+
</a>
33+
</p>
34+
</>
35+
);
36+
}
37+
38+
export default Excerpt;
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)