索引和查询文档

了解如何将 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 查询引擎文档,其中包含所有查询功能的完整描述和示例。

评价此页
返回顶部 ↑