Redis 作为文档数据库快速入门指南
提示
来自deepseek解释
原文链接:https://redis.io/docs/latest/develop/get-started/document-database/
代码示例图例
以下代码示例展示了如何使用不同的编程语言和客户端库执行相同的操作:
- Redis CLI:Redis 的命令行界面
- C#(同步):StackExchange.Redis 同步客户端
- C#(异步):StackExchange.Redis 异步客户端
- Go:go-redis 客户端
- Java(同步 - Jedis):Jedis 同步客户端
- Java(异步 - Lettuce):Lettuce 异步客户端
- Java(响应式 - Lettuce):Lettuce 响应式/流式客户端
- JavaScript(Node.js):node-redis 客户端
- PHP:Predis 客户端
- Python:redis-py 客户端
- Rust(同步):redis-rs 同步客户端
- Rust(异步):redis-rs 异步客户端
每个代码示例都展示了跨不同语言的相同基本操作。具体语法和模式因语言和客户端库而异,但底层的 Redis 命令和行为保持一致。
本快速入门指南将向您展示如何:
- 创建二级索引
- 添加 JSON 文档
- 搜索和查询您的数据
本文中的示例引用了一个简单的自行车库存,包含具有以下结构的 JSON 文档:
{
"brand": "品牌名称",
"condition": "new | used | refurbished",
"description": "描述",
"model": "型号",
"price": 0
}设置
开始使用 Redis 的最简单方式是使用 Redis Cloud:
- 创建一个免费账户。
2. 按照说明创建一个免费数据库。
这个免费的 Redis Cloud 数据库开箱即用地包含所有 Redis 开源功能。
您也可以选择遵循安装指南在本地计算机上安装 Redis 开源版。
连接
第一步是连接到您的 Redis 开源数据库。您可以在本文档站的工具部分中找到有关连接选项的更多详细信息。以下示例展示了如何连接到运行在 localhost(-h 127.0.0.1)并监听默认端口(-p 6379)的 Redis 开源服务器:
基础篇:使用 redis-cli 通过主机和端口参数连接到 Redis 服务器
难度: 初级
命令: REDIS-CLI
可用语言: Redis CLI, C#, Go, Java(同步 - Jedis), JavaScript(Node.js), Python
Redis CLI
> redis-cli -h 127.0.0.1 -p 6379C#
var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();
var ft = db.FT();
var json = db.JSON();Go
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // 无密码
DB: 0, // 使用默认 DB
Protocol: 2,
})Java(同步 - Jedis)
RedisClient jedis = RedisClient.create("localhost", 6379);JavaScript(Node.js)
const client = createClient();
client.on('error', err => console.log('Redis Client Error', err));
await client.connect();Python
r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)您可以从 Redis Cloud 数据库配置页面复制并粘贴连接详情。以下是一个托管在 AWS 区域 us-east-1 并监听端口 16379 的云数据库的连接字符串示例:redis-16379.c283.us-east-1-4.ec2.cloud.redislabs.com:16379。连接字符串的格式为 host:port。您还必须复制并粘贴云数据库的用户名和密码,然后将凭证传递给客户端,或在连接建立后使用 AUTH 命令。
创建索引
正如内存数据结构存储快速入门指南中所述,Redis 允许您直接通过键访问条目。您还学习了如何扫描键空间。虽然您可以使用其他数据结构(如哈希和有序集合)作为二级索引,但您的应用程序需要手动维护这些索引。Redis 是一个文档数据库,允许您声明哪些字段会被自动索引。Redis 目前支持对哈希和 JSON 文档创建二级索引。
以下示例展示了 FT.CREATE 命令,该命令创建了一个包含一些文本字段、一个数字字段(price)和一个标签字段(condition)的索引。文本字段的权重为 1.0,意味着它们在全文搜索的上下文中具有相同的相关性。字段名称遵循 JSONPath 表示法。每个这样的索引字段映射到 JSON 文档中的一个属性。
基础篇:使用 FT.CREATE 在 JSON 文档上创建包含文本、数字和标签字段的索引
难度: 初级
命令: FT.CREATE
复杂度:
- FT.CREATE: O(K)
可用语言: Redis CLI, C#, Go, Java(同步 - Jedis), JavaScript(Node.js), Python
Redis CLI
> FT.CREATE idx:bicycle ON JSON PREFIX 1 bicycle: SCORE 1.0 SCHEMA $.brand AS brand TEXT WEIGHT 1.0 $.model AS model TEXT WEIGHT 1.0 $.description AS description TEXT WEIGHT 1.0 $.price AS price NUMERIC $.condition AS condition TAG SEPARATOR ,
OKC#
var schema = new Schema()
.AddTextField(new FieldName("$.Brand", "Brand"))
.AddTextField(new FieldName("$.Model", "Model"))
.AddTextField(new FieldName("$.Description", "Description"))
.AddNumericField(new FieldName("$.Price", "Price"))
.AddTagField(new FieldName("$.Condition", "Condition"));
ft.Create(
"idx:bicycle",
new FTCreateParams().On(IndexDataType.JSON).Prefix("bicycle:"),
schema);Go
schema := []*redis.FieldSchema{
{
FieldName: "$.brand",
As: "brand",
FieldType: redis.SearchFieldTypeText,
},
{
FieldName: "$.model",
As: "model",
FieldType: redis.SearchFieldTypeText,
},
{
FieldName: "$.description",
As: "description",
FieldType: redis.SearchFieldTypeText,
},
}
_, err := rdb.FTCreate(ctx, "idx:bicycle",
&redis.FTCreateOptions{
Prefix: []interface{}{"bicycle:"},
OnJSON: true,
},
schema...,
).Result()
if err != nil {
panic(err)
}Java(同步 - Jedis)
SchemaField[] schema = {
TextField.of("$.brand").as("brand"),
TextField.of("$.model").as("model"),
TextField.of("$.description").as("description"),
NumericField.of("$.price").as("price"),
TagField.of("$.condition").as("condition")
};
jedis.ftCreate("idx:bicycle",
FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("bicycle:"),
schema
);JavaScript(Node.js)
const schema = {
'$.brand': {
type: SCHEMA_FIELD_TYPE.TEXT,
SORTABLE: true,
AS: 'brand'
},
'$.model': {
type: SCHEMA_FIELD_TYPE.TEXT,
AS: 'model'
},
'$.description': {
type: SCHEMA_FIELD_TYPE.TEXT,
AS: 'description'
},
'$.price': {
type: SCHEMA_FIELD_TYPE.NUMERIC,
AS: 'price'
},
'$.condition': {
type: SCHEMA_FIELD_TYPE.TAG,
AS: 'condition'
}
};
try {
await client.ft.create('idx:bicycle', schema, {
ON: 'JSON',
PREFIX: 'bicycle:'
});
} catch (e) {
if (e.message === 'Index already exists') {
console.log('索引已存在,跳过创建。');
} else {
// 出错了,可能 RediSearch 没有安装...
console.error(e);
process.exit(1);
}
}Python
schema = (
TextField("$.brand", as_name="brand"),
TextField("$.model", as_name="model"),
TextField("$.description", as_name="description"),
NumericField("$.price", as_name="price"),
TagField("$.condition", as_name="condition"),
)
index = r.ft("idx:bicycle")
index.create_index(
schema,
definition=IndexDefinition(prefix=["bicycle:"], index_type=IndexType.JSON),
)任何键前缀为 bicycle: 的已存在 JSON 文档都会自动添加到索引中。此外,索引创建后创建或修改的具有该前缀的任何 JSON 文档都会被添加或重新添加到索引中。
添加 JSON 文档
以下示例展示了如何使用 JSON.SET 命令创建新的 JSON 文档:
基础篇:使用 JSON.SET 向 Redis 添加 JSON 文档
难度: 初级
命令: JSON.SET
复杂度:
- JSON.SET: O(M+N)
可用语言: Redis CLI, C#, Go, Java(同步 - Jedis), JavaScript(Node.js), Python
Redis CLI
> JSON.SET "bicycle:0" "." "{\"brand\": \"Velorim\", \"model\": \"Jigger\", \"price\": 270, \"description\": \"Small and powerful, the Jigger is the best ride for the smallest of tikes! This is the tiniest kids\\u2019 pedal bike on the market available without a coaster brake, the Jigger is the vehicle of choice for the rare tenacious little rider raring to go.\", \"condition\": \"new\"}"
... 输出已截断 ...
> JSON.SET "bicycle:9" "." "{\"model\": \"ThrillCycle\", \"brand\": \"BikeShind\", \"price\": 815, \"description\": \"An artsy, retro-inspired bicycle that\\u2019s as functional as it is pretty: The ThrillCycle steel frame offers a smooth ride. A 9-speed drivetrain has enough gears for coasting in the city, but we wouldn\\u2019t suggest taking it to the mountains. Fenders protect you from mud, and a rear basket lets you transport groceries, flowers and books. The ThrillCycle comes with a limited lifetime warranty, so this little guy will last you long past graduation.\", \"condition\": \"refurbished\"}"
OKC#
for (int i = 0; i < bicycles.Length; i++)
{
json.Set($"bicycle:{i}", "$", bicycles[i]);
}Go
for i, bicycle := range bicycles {
_, err := rdb.JSONSet(
ctx,
fmt.Sprintf("bicycle:%v", i),
"$",
bicycle,
).Result()
if err != nil {
panic(err)
}
}Java(同步 - Jedis)
for (int i = 0; i < bicycles.length; i++) {
jedis.jsonSetWithEscape(String.format("bicycle:%d", i), bicycles[i]);
}JavaScript(Node.js)
await Promise.all(
bicycles.map((bicycle, i) => client.json.set(`bicycle:${i}`, '$', bicycle))
);Python
for bid, bicycle in enumerate(bicycles):
r.json().set(f"bicycle:{bid}", Path.root_path(), bicycle)使用 Redis Search 进行搜索和查询
通配符查询
您可以使用 FT.SEARCH 命令检索所有已索引的文档。请注意下面的 LIMIT 子句,它允许结果分页。
基础篇:使用 FT.SEARCH 配合通配符查询检索所有已索引的文档
难度: 初级
命令: FT.SEARCH
复杂度:
- FT.SEARCH: O(N)
可用语言: Redis CLI, C#, Go, Java(同步 - Jedis), JavaScript(Node.js), Python
Redis CLI
> FT.SEARCH "idx:bicycle" "*" LIMIT 0 10
1) (integer) 10
2) "bicycle:1"
3) 1) "$"
2) "{\"brand\":\"Bicyk\",\"model\":\"Hillcraft\",\"price\":1200,\"description\":\"Kids want to ride with as little weight as possible. Especially on an incline! They may be at the age when a 27.5\\\" wheel bike is just too clumsy coming off a 24\\\" bike. The Hillcraft 26 is just the solution they need!\",\"condition\":\"used\"}"
4) "bicycle:2"
5) 1) "$"
2) "{\"brand\":\"Nord\",\"model\":\"Chook air 5\",\"price\":815,\"description\":\"The Chook Air 5 gives kids aged six years and older a durable and uberlight mountain bike for their first experience on tracks and easy cruising through forests and fields. The lower top tube makes it easy to mount and dismount in any situation, giving your kids greater safety on the trails.\",\"condition\":\"used\"}"
... 输出已截断 ...
20) "bicycle:8"
21) 1) "$"
2) "{\"brand\":\"nHill\",\"model\":\"Summit\",\"price\":1200,\"description\":\"This budget mountain bike from nHill performs well both on bike paths and on the trail. The fork with 100mm of travel absorbs rough terrain. Fat Kenda Booster tires give you grip in corners and on wet trails. The Shimano Tourney drivetrain offered enough gears for finding a comfortable pace to ride uphill, and the Tektro hydraulic disc brakes break smoothly. Whether you want an affordable bike that you can take to work, but also take trail in mountains on the weekends or you\xe2\x80\x99re just after a stable, comfortable ride for the bike path, the Summit gives a good value for money.\",\"condition\":\"new\"}"C#
var query1 = new Query("*");
var res1 = ft.Search("idx:bicycle", query1).Documents;
Console.WriteLine(string.Join("\n", res1.Count()));
// 输出: 找到文档数: 10Go
wCardResult, err := rdb.FTSearch(ctx, "idx:bicycle", "*").Result()
if err != nil {
panic(err)
}
fmt.Printf("找到文档数: %v\n", wCardResult.Total)
// >>> 找到文档数: 10Java(同步 - Jedis)
Query query1 = new Query("*");
List<Document> result1 = jedis.ftSearch("idx:bicycle", query1).getDocuments();
System.out.println("找到文档数:" + result1.size());
// 输出: 找到文档数: 10JavaScript(Node.js)
let result = await client.ft.search('idx:bicycle', '*', {
LIMIT: {
from: 0,
size: 10
}
});
console.log(JSON.stringify(result, null, 2));
/*
{
"total": 10,
"documents": ...
}
*/Python
res = index.search(Query("*"))
print("找到文档数:", res.total)
# >>> 找到文档数: 10单词语全文查询
以下命令展示了一个简单的单词语查询,用于查找具有特定型号的所有自行车:
基础篇:使用 FT.SEARCH 执行单词语全文查询,查找匹配特定字段值的文档
难度: 初级
命令: FT.SEARCH
复杂度:
- FT.SEARCH: O(N)
可用语言: Redis CLI, C#, Go, Java(同步 - Jedis), JavaScript(Node.js), Python
Redis CLI
> FT.SEARCH "idx:bicycle" "@model:Jigger" LIMIT 0 10
1) (integer) 1
2) "bicycle:0"
3) 1) "$"
2) "{\"brand\":\"Velorim\",\"model\":\"Jigger\",\"price\":270,\"description\":\"Small and powerful, the Jigger is the best ride for the smallest of tikes! This is the tiniest kids\xe2\x80\x99 pedal bike on the market available without a coaster brake, the Jigger is the vehicle of choice for the rare tenacious little rider raring to go.\",\"condition\":\"new\"}"C#
var query2 = new Query("@Model:Jigger");
var res2 = ft.Search("idx:bicycle", query2).Documents;
Console.WriteLine(string.Join("\n", res2.Select(x => x["json"])));
// 输出: {"Brand":"Moore PLC","Model":"Award Race","Price":3790.76,
// "Description":"This olive folding bike features a carbon frame
// and 27.5 inch wheels. This folding bike is perfect for compact
// storage and transportation.","Condition":"new"}Go
stResult, err := rdb.FTSearch(
ctx,
"idx:bicycle",
"@model:Jigger",
).Result()
if err != nil {
panic(err)
}
fmt.Println(stResult)
// >>> {1 [{bicycle:0 <nil> <nil> <nil> map[$:{"brand":"Velorim", ...Java(同步 - Jedis)
Query query2 = new Query("@model:Jigger");
List<Document> result2 = jedis.ftSearch("idx:bicycle", query2).getDocuments();
System.out.println(result2);
// 输出: [id:bicycle:0, score: 1.0, payload:null,
// properties:[$={"brand":"Velorim","model":"Jigger","price":270,"description":"Small and powerful, the Jigger is the best ride for the smallest of tikes! This is the tiniest kids’ pedal bike on the market available without a coaster brake, the Jigger is the vehicle of choice for the rare tenacious little rider raring to go.","condition":"new"}]]JavaScript(Node.js)
result = await client.ft.search(
'idx:bicycle',
'@model:Jigger',
{
LIMIT: {
from: 0,
size: 10
}
});
console.log(JSON.stringify(result, null, 2));
/*
{
"total": 1,
"documents": [{
"id": "bicycle:0",
"value": {
"brand": "Velorim",
"model": "Jigger",
"price": 270,
"description": "Small and powerful, the Jigger is the best ride for the smallest of tikes! This is the tiniest kids’ pedal bike on the market available without a coaster brake, the Jigger is the vehicle of choice for the rare tenacious little rider raring to go.",
"condition": "new"
}
}]
}
*/Python
res = index.search(Query("@model:Jigger"))
print(res)
# >>> Result{1 total, docs: [
# Document {
# 'id': 'bicycle:0',
# 'payload': None,
# 'json': '{
# "brand":"Velorim",
# "model":"Jigger",
# "price":270,
# ...
# "condition":"new"
# }'
# }]}精确匹配查询
下面是一个执行精确匹配查询的命令,用于查找品牌名为 Noka Bikes 的所有自行车。在对文本字段构造精确匹配查询时,您必须在搜索词周围使用双引号。
基础篇:使用 FT.SEARCH 配合双引号执行精确匹配查询,查找具有精确字段值的文档
难度: 初级
命令: FT.SEARCH
复杂度:
- FT.SEARCH: O(N)
可用语言: Redis CLI, C#, Go, Java(同步 - Jedis), JavaScript(Node.js), Python
Redis CLI
> FT.SEARCH "idx:bicycle" "@brand:\"Noka Bikes\"" LIMIT 0 10
1) (integer) 1
2) "bicycle:4"
3) 1) "$"
2) "{\"brand\":\"Noka Bikes\",\"model\":\"Kahuna\",\"price\":3200,\"description\":\"Whether you want to try your hand at XC racing or are looking for a lively trail bike that's just as inspiring on the climbs as it is over rougher ground, the Wilder is one heck of a bike built specifically for short women. Both the frames and components have been tweaked to include a women\xe2\x80\x99s saddle, different bars and unique colourway.\",\"condition\":\"used\"}"C#
var query4 = new Query("@Brand:\"Noka Bikes\"");
var res4 = ft.Search("idx:bicycle", query4).Documents;
Console.WriteLine(string.Join("\n", res4.Select(x => x["json"])));
// 输出: {"Brand":"Moore PLC","Model":"Award Race","Price":3790.76,
// "Description":"This olive folding bike features a carbon frame
// and 27.5 inch wheels. This folding bike is perfect for compact
// storage and transportation.","Condition":"new"}Go
exactMatchResult, err := rdb.FTSearch(
ctx,
"idx:bicycle",
"@brand:\"Noka Bikes\"",
).Result()
if err != nil {
panic(err)
}
fmt.Println(exactMatchResult)
// >>> {1 [{bicycle:4 <nil> <nil> <nil> map[$:{"brand":"Noka Bikes"...Java(同步 - Jedis)
Query query5 = new Query("@brand:\"Noka Bikes\"");
List<Document> result5 = jedis.ftSearch("idx:bicycle", query5).getDocuments();
System.out.println(result5);
// 输出: [id:bicycle:4, score: 1.0, payload:null,
// properties:[$={"brand":"Noka Bikes","model":"Kahuna","price":3200,"description":"Whether you want to try your hand at XC racing or are looking for a lively trail bike that's just as inspiring on the climbs as it is over rougher ground, the Wilder is one heck of a bike built specifically for short women. Both the frames and components have been tweaked to include a women’s saddle, different bars and unique colourway.","condition":"used"}]]JavaScript(Node.js)
result = await client.ft.search(
'idx:bicycle',
'@brand:"Noka Bikes"',
{
LIMIT: {
from: 0,
size: 10
}
}
);
console.log(JSON.stringify(result, null, 2));
/*
{
"total": 1,
"documents": [{
"id": "bicycle:4",
"value": {
"brand": "Noka Bikes",
"model": "Kahuna",
"price": 3200,
"description": "Whether you want to try your hand at XC racing or are looking for a lively trail bike that's just as inspiring on the climbs as it is over rougher ground, the Wilder is one heck of a bike built specifically for short women. Both the frames and components have been tweaked to include a women’s saddle, different bars and unique colourway.",
"condition": "used"
}
}]
}
*/Python
res = index.search(Query('@brand:"Noka Bikes"'))
print(res)
# >>> Result{1 total, docs: [
# Document {
# 'id': 'bicycle:4',
# 'payload': None,
# 'json': '{
# "brand":"Noka Bikes",
# "model":"Kahuna",
# "price":3200,
# ...
# "condition":"used"
# }'
# }]}请参阅查询文档以了解如何进行更高级的查询。
后续步骤
您可以在以下快速入门指南中了解有关如何使用 Redis 开源版作为向量数据库的更多信息: