抄袭自前任程序员的创意。。。
如果我想输入“雄英”来找到游戏库中的所有带有这两个字的游戏,该怎样用redis来实现呢?
原理:
1, 将所有的游戏名字读出来,拆分成单个汉字
2, 将这些汉字作为redis集合的键,写入redis,每个集合里的值是所有那些游戏名字中包含此汉字的游戏的id
3, 当用户输入文字的时候通过ajax异步请求,将用户输入传给PHP
4, 将输入的文字拆分成单个汉字, 分别找到这些汉字在redis中的集合值
5, 取出来,求交集,就找到了同时包含这几个汉字的游戏的id
6, 最后到数据库里查出来相应的游戏信息即可
缺点: 删除数据不方便
具体实现代码:
redis代码:iredis.php
<?php
class iRedis extends Redis{
public function __construct(){
$this->connect('127.0.0.1', 6379);
}
//获取某个key之下的redis数据
public function getIndex($key){
return $this->sMembers($key);
}
//删除某个key之下的redis数据
public function delIndex($key){
return $this->sMembers($key);
}
}
game模型类代码:
<?php
require_once 'database.php';
require_once 'iredis.php';
class Game extends Database{
public $instance;
public $redis;
public $table = 'game';
public function __construct(){
$this->instance = self::getInstance();
$this->redis = new iRedis();
}
//为游戏创建索引
public function createIndexes(){
$sql = "select * from $this->table";
$games = $this->instance->query($sql)->fetch_all(MYSQLI_ASSOC);
$splitedGames = $this->splitGameName($games);
foreach($splitedGames as $k => $v){
$this->redis->sAdd($k, serialize($v));
}
}
//根据id获取游戏名
public function getGameByGameid($gameid){
$gameidStr = implode(',', $gameid);
$sql = "select name from $this->table where id in ($gameidStr)";
$gameName = $this->instance->query($sql)->fetch_all(MYSQLI_ASSOC);
return $gameName;
}
//根据用户输入获取提示信息
public function getHint($keyword){
if(empty($keyword)){
return "";
}
if(mb_strlen($keyword, 'utf-8') == 1){
// $gameids = unserialize($this->redis->getIndex($keyword));
$unserializedGameids = $this->redis->getIndex($keyword);
$gameids = unserialize($unserializedGameids[0]);
if(empty($gameids) || !is_array($gameids)){
return "";
}
return $this->getGameByGameid($gameids);
}
$gameids = array();
$keywordLenth = mb_strlen($keyword, 'utf-8');
for ($i = 0; $i < $keywordLenth; $i++) {
$keywordPiece = mb_substr($keyword, $i, 1, 'utf-8');
$unserializedGameids = $this->redis->getIndex($keywordPiece);
$gameid = unserialize($unserializedGameids[0]);
if(!empty($gameid)){
$gameids = empty($gameids) ? $gameid : array_intersect($gameids, $gameid);
}
}
if(empty($gameids) || !is_array($gameids)){
return "";
}
return $this->getGameByGameid($gameids);
}
//将游戏名进行拆分
private function splitGameName($games){
$splitedGames = array();
foreach ($games as $game) {
$ganeNameLenth = mb_strlen($game['name'], 'utf-8');
for ($i = 0; $i < $ganeNameLenth; $i++) {
$gameNamePiece = mb_substr($game['name'], $i, 1, 'utf-8');
$splitedGames[$gameNamePiece][] = $game['id'];
}
}
return $splitedGames;
}
}
database.php
<?php
class Database{
//只是为了演示,通常情况下数据库的配置是会单独写在配置文件中的
private static $_dbConfig = array(
'host' => '127.0.0.1',
'username' => 'root',
'pwd' => '',
'dbname' => 'bussiness'
);
private static $_instance;
public static function getInstance(){
if(is_null(self::$_instance)){
self::$_instance = new mysqli(self::$_dbConfig['host'], self::$_dbConfig['username'], self::$_dbConfig['pwd'], self::$_dbConfig['dbname']);
if(self::$_instance->connect_errno){
throw new Exception(self::$_instance->connect_error);
}
}
return self::$_instance;
}
}
index.php
<?php
require_once 'game.php';
require_once 'iredis.php';
$redis = new iRedis();
$game = new Game();
$game->createIndexes();
var_dump($game->getHint('雄英'));
数据库中game表中的测试数据入下截图所示:
执行index.php中的代码结果如下图所示:
点评:可以进一步修改,直接使用redis自身的功能求交集。