redis实战:使用redis实现自动补全

抄袭自前任程序员的创意。。。

如果我想输入“雄英”来找到游戏库中的所有带有这两个字的游戏,该怎样用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自身的功能求交集。





评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值