转载:http://blog.csdn.net/u011250882/article/details/48632379
如果我想输入“雄英”来找到游戏库中的所有带有这两个字的游戏,该怎样用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自身的功能求交集。