索引和查询文档
了解如何将 Redis 查询引擎与 JSON 和哈希文档一起使用。
此示例展示了如何为 JSON 文档创建搜索索引并对索引运行查询。然后继续展示了等效的 哈希 文档代码中的细微差异。
初始化
确保您已安装 Redis 开源版 或其他 Redis 服务器。如果尚未安装,还需要安装 Predis
客户端库。
添加以下依赖项
<?php
require 'vendor/autoload.php';
use Predis\Client as PredisClient;
use Predis\Command\Argument\Search\AggregateArguments;
use Predis\Command\Argument\Search\CreateArguments;
use Predis\Command\Argument\Search\SearchArguments;
use Predis\Command\Argument\Search\SchemaFields\NumericField;
use Predis\Command\Argument\Search\SchemaFields\TextField;
use Predis\Command\Argument\Search\SchemaFields\TagField;
use Predis\Command\Argument\Search\SchemaFields\VectorField;
创建数据
创建一些测试数据以添加到您的数据库中
$user1 = json_encode([
'name' => 'Paul John',
'email' => '[email protected]',
'age' => 42,
'city' => 'London',
], JSON_THROW_ON_ERROR);
$user2 = json_encode([
'name' => 'Eden Zamir',
'email' => '[email protected]',
'age' => 29,
'city' => 'Tel Aviv',
], JSON_THROW_ON_ERROR);
$user3 = json_encode([
'name' => 'Paul Zamir',
'email' => '[email protected]',
'age' => 35,
'city' => 'Tel Aviv',
], JSON_THROW_ON_ERROR);
添加索引
连接到您的 Redis 数据库。以下代码展示了最基本的连接,但请参阅连接到服务器以了解更多可用的连接选项。
$r = new PredisClient([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'database' => 0,
]);
创建一个索引。在此示例中,仅索引键前缀为 user:
的 JSON 文档。有关更多信息,请参阅查询语法。
$schema = [
new TextField('$.name', 'name'),
new TagField('$.city', 'city'),
new NumericField('$.age', "age"),
];
try {
$r->ftCreate("idx:users", $schema,
(new CreateArguments())
->on('JSON')
->prefix(["user:"]));
}
catch (Exception $e) {
echo $e->getMessage(), PHP_EOL;
}
添加数据
将这三组用户数据作为 JSON 对象添加到数据库。如果您使用带有 user:
前缀的键,那么 Redis 会在您添加对象时自动为其创建索引。
$r->jsonset('user:1', '$', $user1);
$r->jsonset('user:2', '$', $user2);
$r->jsonset('user:3', '$', $user3);
查询数据
您现在可以使用索引搜索 JSON 对象。下面的查询搜索任意字段中包含文本 "Paul" 且 age
值在 30 到 40 之间的对象。
$res = $r->ftSearch("idx:users", "Paul @age:[30 40]");
echo json_encode($res), PHP_EOL;
// >>> [1,"user:3",["$","{\"name\":\"Paul Zamir\",\"email\":\"[email protected]\",\"age\":35,\"city\":\"London\"}"]]
指定查询选项以仅返回 city
字段
$arguments = new SearchArguments();
$arguments->addReturn(3, '$.city', true, 'thecity');
$arguments->dialect(2);
$arguments->limit(0, 5);
$res = $r->ftSearch("idx:users", "Paul", $arguments);
echo json_encode($res), PHP_EOL;
// >>> [2,"user:1",["thecity","London"],"user:3",["thecity","Tel Aviv"]]
使用聚合查询来统计每个城市的所有用户数。
$ftAggregateArguments = (new AggregateArguments())
->groupBy('@city')
->reduce('COUNT', true, 'count');
$res = $r->ftAggregate('idx:users', '*', $ftAggregateArguments);
echo json_encode($res), PHP_EOL;
// >>> [2,["city","London","count","1"],["city","Tel Aviv","count","2"]]
与哈希文档的区别
哈希文档的索引与 JSON 索引非常相似,但您需要指定一些略有不同的选项。
创建哈希索引的模式时,您不需要为字段添加别名,因为无论如何您都使用基本名称访问字段。此外,创建索引时,On()
选项必须使用 HASH
。下面的代码展示了这些更改,创建了一个名为 hash-idx:users
的新索引,该索引与前面示例中用于 JSON 文档的 idx:users
索引相同。
$hashSchema = [
new TextField('name'),
new TagField('city'),
new NumericField('age'),
];
try {
$r->ftCreate("hash-idx:users", $hashSchema,
(new CreateArguments())
->on('HASH')
->prefix(["huser:"]));
}
catch (Exception $e) {
echo $e->getMessage(), PHP_EOL;
}
您使用 hmset()
而不是 jsonset()
来添加哈希文档。直接将字段作为数组提供,无需使用 json_encode()
。
$r->hmset('huser:1', [
'name' => 'Paul John',
'email' => '[email protected]',
'age' => 42,
'city' => 'London',
]);
$r->hmset('huser:2', [
'name' => 'Eden Zamir',
'email' => '[email protected]',
'age' => 29,
'city' => 'Tel Aviv',
]);
$r->hmset('huser:3', [
'name' => 'Paul Zamir',
'email' => '[email protected]',
'age' => 35,
'city' => 'Tel Aviv',
]);
查询命令对于哈希和 JSON 的工作方式在这里是相同的(但哈希索引的名称不同)。结果的格式几乎相同,只是字段直接在结果数组中返回,而不是以 $
作为键的 JSON 字符串中返回。
$res = $r->ftSearch("hash-idx:users", "Paul @age:[30 40]");
echo json_encode($res), PHP_EOL;
// >>> [1,"huser:3",["age","35","city","Tel Aviv","email","[email protected]","name","Paul Zamir"]]
更多信息
请参阅Redis 查询引擎文档,其中包含所有查询功能的完整描述和示例。