索引和查询文档
了解如何使用 Redis Query Engine 处理 JSON 和哈希文档。
此示例展示了如何为 JSON 文档创建搜索索引并针对该索引运行查询。然后,它继续展示了处理哈希文档的等效代码中的细微差异。
初始化
确保您已安装 Redis 开源版或其他 Redis 服务器。如果您尚未安装,请安装 node-redis
客户端库。
添加以下依赖项
import {
createClient,
SchemaFieldTypes,
AggregateGroupByReducers,
AggregateSteps,
} from 'redis';
创建数据
创建一些测试数据添加到您的数据库。下面显示的示例数据兼容 JSON 和哈希对象。
const user1 = {
name: 'Paul John',
email: '[email protected]',
age: 42,
city: 'London'
};
const user2 = {
name: 'Eden Zamir',
email: '[email protected]',
age: 29,
city: 'Tel Aviv'
};
const user3 = {
name: 'Paul Zamir',
email: '[email protected]',
age: 35,
city: 'Tel Aviv'
};
添加索引
连接到您的 Redis 数据库。下面的代码展示了最基本的连接方式,但请参阅连接到服务器以了解更多可用的连接选项。
const client = await createClient();
await client.connect();
创建索引。在此示例中,仅索引键前缀为 user:
的 JSON 文档。有关更多信息,请参阅查询语法。
await client.ft.create('idx:users', {
'$.name': {
type: SchemaFieldTypes.TEXT,
AS: 'name'
},
'$.city': {
type: SchemaFieldTypes.TEXT,
AS: 'city'
},
'$.age': {
type: SchemaFieldTypes.NUMERIC,
AS: 'age'
}
}, {
ON: 'JSON',
PREFIX: 'user:'
});
添加数据
将三组用户数据作为 JSON 对象添加到数据库中。如果您使用键前缀为 user:
的键,Redis 将在您添加对象时自动对其进行索引。请注意,将命令放在 Promise.all()
调用中是创建管道的一种简单方式,这比单独发送命令更高效。
const [user1Reply, user2Reply, user3Reply] = await Promise.all([
client.json.set('user:1', '$', user1),
client.json.set('user:2', '$', user2),
client.json.set('user:3', '$', user3)
]);
查询数据
现在您可以使用索引来搜索 JSON 对象。下面的查询搜索在任何字段中包含文本“Paul”且 age
值在 30 到 40 范围内的对象
let findPaulResult = await client.ft.search('idx:users', 'Paul @age:[30 40]');
console.log(findPaulResult.total); // >>> 1
findPaulResult.documents.forEach(doc => {
console.log(`ID: ${doc.id}, name: ${doc.value.name}, age: ${doc.value.age}`);
});
指定查询选项以仅返回 city
字段
let citiesResult = await client.ft.search('idx:users', '*',{
RETURN: 'city'
});
console.log(citiesResult.total); // >>> 3
citiesResult.documents.forEach(cityDoc => {
console.log(cityDoc.value);
});
使用聚合查询统计每个城市的用户数。
let aggResult = await client.ft.aggregate('idx:users', '*', {
STEPS: [{
type: AggregateSteps.GROUPBY,
properties: '@city',
REDUCE: [{
type: AggregateGroupByReducers.COUNT,
AS: 'count'
}]
}]
});
console.log(aggResult.total); // >>> 2
aggResult.results.forEach(result => {
console.log(`${result.city} - ${result.count}`);
});
最后,关闭与 Redis 的连接。
await client.quit();
与哈希文档的区别
哈希文档的索引与 JSON 索引非常相似,但您需要指定一些略微不同的选项。
为哈希索引创建模式时,您无需为字段添加别名,因为无论如何您都使用基本名称来访问字段。此外,在创建索引时,必须为 ON
选项使用 HASH
。下面的代码展示了这些更改,使用了一个名为 hash-idx:users
的新索引,它与前面示例中用于 JSON 文档的 idx:users
索引相同。
await client.ft.create('hash-idx:users', {
'name': {
type: SchemaFieldTypes.TEXT
},
'city': {
type: SchemaFieldTypes.TEXT
},
'age': {
type: SchemaFieldTypes.NUMERIC
}
}, {
ON: 'HASH',
PREFIX: 'huser:'
});
您使用 hSet()
添加哈希文档,而不是 json.set()
,但相同的扁平 userX
对象对于哈希和 JSON 同样适用
const [huser1Reply, huser2Reply, huser3Reply] = await Promise.all([
client.hSet('huser:1', user1),
client.hSet('huser:2', user2),
client.hSet('huser:3', user3)
]);
这里的查询命令对于哈希与对于 JSON 的工作方式相同(但哈希索引的名称不同)。结果的格式也相同
let findPaulHashResult = await client.ft.search(
'hash-idx:users', 'Paul @age:[30 40]'
);
console.log(findPaulHashResult.total); // >>> 1
findPaulHashResult.documents.forEach(doc => {
console.log(`ID: ${doc.id}, name: ${doc.value.name}, age: ${doc.value.age}`);
});
// >>> ID: huser:3, name: Paul Zamir, age: 35
更多信息
请参阅Redis Query Engine 文档,了解所有查询功能的完整说明和示例。