一、先启动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
最后编辑:admin 更新时间:2026-06-01 20:10