一、先启动Redis Stack

docker run -d –name redis-stack -p 7379:6379 -p 8001:8001 redis/redis-stack:latest

二、创建索引

<?php
try{
  // 连接 Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 7379);

$redis->rawCommand('FT.CREATE', 'idx:alarm',
    'ON', 'JSON',
    'PREFIX', 1, 'alarm:',
    'SCHEMA',
    '$.alarm_id', 'AS', 'alarm_id', 'NUMERIC',
    '$.macid', 'AS', 'macid', 'TAG',
    '$.bms_alarm_code', 'AS', 'code', 'NUMERIC',
    '$.ctime', 'AS', 'ctime', 'NUMERIC',
    '$.level', 'AS', 'level', 'TAG',
    '$.admin_id', 'AS', 'admin_id', 'TAG',
    '$.delete_time', 'AS', 'delete_time', 'NUMERIC'
);
}catch(\Exception $e){
  echo $e->getMessage();
}

三、写入数据,统计数据

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 7379);
// $redis->auth('你的密码');

// 重要:关闭 Redis 序列化(必须加,否则 JSON 格式错乱)
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE);

echo "开始写入数据...\n";

for ($i = 1; $i <= 100; $i++) {

    // 所有字段随机生成
    $alarm = [
        'alarm_id' => $i, // 自增ID,不重复
        'macid' => '01' . rand(100000000, 999999999), // 12位随机设备号
        'bms_alarm_code' => rand(1, 20), // 1-20随机
        'ctime' => rand(1700000000, 1800000000), // 随机时间戳
        'level' => strval(rand(1, 3)), // 告警级别 1-3
        'admin_id' => strval(rand(200, 700)),
        'delete_time' => 0,
    ];

    // Key 规则
    $key = "alarm:{$alarm['alarm_id']}";

    // 写入 Redis JSON
    $redis->rawCommand('JSON.SET', $key, '$', json_encode($alarm));
}

echo "\n开始执行统计...\n";

$adminIdStr = "";
for ($i = 200; $i <= 700; $i++) {
    $adminIdStr .= strval($i) . "|";
}
$adminIdStr = substr($adminIdStr, 0, -1);
$level = "2";

try {
    // 拼接查询条件
    $query = '@admin_id:{' . $adminIdStr . '} @level:{' . $level . '}';

    $info = $redis->rawCommand('FT.INFO', 'idx:alarm');
    //print_r($info);

    $res = $redis->rawCommand(
        'FT.AGGREGATE',   // RediSearch 聚合查询命令,类似 SQL 的 SELECT ... GROUP BY
        'idx:alarm',    // 要查询的索引名称,对应 FT.CREATE 时定义的名字
        $query,                   // 查询条件,如 @admin_id:{200|...|700} @level:{2}
        'GROUPBY', '0',           // GROUPBY 0 表示不按任何字段分组,即对所有匹配文档整体聚合(类似 SQL 的 SELECT COUNT(*) 无 GROUP BY)
        'REDUCE',                 // 声明一个聚合函数,跟在 GROUPBY 之后
        'COUNT',                  // 聚合函数名:COUNT,统计每组匹配的文档数量
        '0',                      // COUNT 函数的参数个数,0 表示 COUNT 不需要额外字段参数(它直接数行数)
        'AS', 'total'             // 给聚合结果起别名,最终返回结果中字段名为 total(类似 SQL 的 COUNT(*) AS total)
    );

    //如果需要按level分组可以这样写
    /*
     $res = $redis->rawCommand(
        'FT.AGGREGATE',
        'idx:alarm',
        $query,
        'GROUPBY', '1', '@level',  // 1表示按1个字段分组,@level是分组字段(必须加@前缀)
        'REDUCE',
        'COUNT',
        '0',
        'AS', 'total'
    );
     */
    //再多点,可以这样写'GROUPBY', '2', '@level', '@admin_id',

    print_r($res);

} catch (\Exception $e) {
    echo $e->getMessage();
}
作者:admin  创建时间:2026-06-01 20:09
最后编辑:admin  更新时间:2026-06-01 20:10
上一篇:
下一篇: