sql like模糊查询,搜索关键字时,增加搜索权重排序及关键字高亮功能(增加带标点空格分词功能)

原网址https://blog.csdn.net/viqecel/article/details/121352227
在此基础上有修改.比如搜索 包含标点的 “硒化 , 锌” 会先分词,再合并.功能简单,实用

一是.thinkphp3的分页用了array_splice()模拟分页,因为需要用到多条sql语句合并查询(sql UNION),thinkphp3的合并查询功能不完善,只能写纯粹的sql语句.

二,合并查询后,需要对搜索词进行相关性,进行权重打分并排序.

完整代码

function search() {
	header("Content-Type:text/html; charset=utf-8");
	$ss=$this->ss;
	$soso=trim(I('soso'));
	//过滤空格防止乱码
	//print_r(1);exit;
	$this->assign('soso',$soso);
	//含有符号时,断句合并多语句查询
	if($soso) {
		$soso2=str_replace(','," " ,$soso);
		$soso2=str_replace(',' ," " , $soso2);
		$soso2=str_replace('。'," " ,$soso2);
		$soso2=str_replace('.' ," " ,$soso2);
		$soso2=str_replace('.' ," " ,$soso2);
		$soso2=str_replace(';' ," " ,$soso2);
		$soso2=str_replace(':',' ' ,$soso2);
		$soso2=str_replace(';',' ' ,$soso2);
		$soso2=str_replace(':',' ' ,$soso2);
		$soso2=str_replace('(',' ' ,$soso2);
		$soso2=str_replace(')',' ' ,$soso2);
		$soso2=str_replace('[',' ' ,$soso2);
		$soso2=str_replace(']',' ' ,$soso2);
		$soso2=str_replace('、',' ' ,$soso2);
		//多个空格转一个
		$soso2=preg_replace("/\s(?=\s)/","\\1", $soso2);
		// $map['title|xinghao|huohao|description|des']=array('like',"%$soso%");//搜索标题或型号			
		$map2['soso']=$soso;
		//用于分页时,网址参数
		$soso2=trim($soso2);//再次去掉前后空格,防止搜索空字符,导致乱码
		$soso3=str_replace(' ','' ,$soso2);
		//soso3为去掉无用标点空格等,得到的全词匹配,匹配时优先级最高
		$cp_class_where['name|content']=array('like',"%$soso3%");
		//标点全去掉,搜索栏目
		$cp_class_where2['soso']=$soso3;
	}
	$arr = explode(' ', $soso2);
	if(count($arr)>1) {
		//说明搜索词中有空格等,需要简单分词
		$sql='';
		//用到合并查询
		foreach ($arr  as $k => $so) {
			$sql.="SELECT `id`,`iss`,`title`,`type`,`xinghao`,`huohao`,`description`,`mycontent`,`ctime`,`pic`,`kucun` FROM `tg_contlist` 
			WHERE ( `title` LIKE '%$so%' OR `xinghao` LIKE '%$so%' OR `huohao` LIKE '%$so%' OR `description` LIKE '%$so%' OR `mycontent` LIKE '%$so%' ) UNION ";
		}
		$sql=rtrim($sql,'UNION ');
	} else {
		//如果不含标点等,则按正常搜索,并直接排序
		$soso=trim($soso2);//去掉括号等非法字符
	if(!$soso){
				  $this->cp_list='';//防止空字符查询
        $this->cp_class_list='';
            $this->display();
			exit;
			}
			
		$sql="SELECT `id`,`iss`,`title`,`type`,`xinghao`,`huohao`,`description`,`mycontent`,`ctime`,`pic`,`kucun`,((case when xinghao like '$soso%' then 100 else 0 end)+
(case when xinghao like '%$soso%' then 90 else 0 end)) as xinghaosort,((case when huohao like '$soso%' then 70 else 0 end)+
(case when huohao like '%$soso%' then 60 else 0 end)) as huohaosort,((case when title like '$soso%' then 400 else 0 end)+
(case when title like '%$soso%' then 300 else 0 end)) as titlesort,((case when description like '$soso%' then 50 else 0 end)+
(case when description like '%$soso%' then 45 else 0 end)) as descriptionsort,((case when mycontent like '$soso%' then 40 else 0 end)+
(case when mycontent like '%$soso%' then 35 else 0 end)) as dessort FROM `tg_contlist` WHERE ( `title` LIKE '%$soso%' OR `xinghao` LIKE '%$soso%' OR `huohao` LIKE '%$soso%' OR `description` LIKE '%$soso%' OR `mycontent` LIKE '%$soso%' ) ORDER BY titlesort desc,xinghaosort desc,huohaosort desc,descriptionsort desc,dessort desc ";
	}
	$result     =   M()->query($sql);
	//print_r($result);exit;
	$cp_list2=array();
	if(count($arr)>1) {
		//数据预处理 增加权重排序虚拟字段 再替换
		foreach ($arr  as  $so4) {
			foreach ($result  as $k => $v) {
				$result[$k]['sort']=0;
				if(stristr($result[$k]['title'],$soso3)) {
					$result[$k]['sort']=300;
				}
				//标题中有 全词,优先级最高 
				//如果标题打分.则下面的条件就算符合,也直接跳过
				//标题中有 部分关键字
				if(stristr($result[$k]['xinghao'],$soso3) && $result[$k]['sort']==0 ) {
					$result[$k]['sort']=295;
				}
				//如果标题打分.则下次遇到直接跳过
				if(stristr($result[$k]['description'],$soso3)&& $result[$k]['sort']==0 ) {
					$result[$k]['sort']=294;
				}
				if(stristr($result[$k]['mycontent'],$soso3) && $result[$k]['sort']==0) {
					$result[$k]['sort']=290;
				}
				if(stristr($result[$k]['title'],$so4) && $result[$k]['sort']==0 ) {
					$result[$k]['sort']=200;
				}
				if(stristr($result[$k]['xinghao'],$so4) && $result[$k]['sort']==0 ) {
					$result[$k]['sort']=195;
				}
				if(stristr($result[$k]['description'],$so4) && $result[$k]['sort']==0 ) {
					$result[$k]['sort']=194;
				}
				if(stristr($result[$k]['mycontent'],$so4) && $result[$k]['sort']==0 ) {
					$result[$k]['sort']=190;
				}
			}
		}
		//排序
		$last_names = array_column($result,'sort');
		//二维数组排序
		array_multisort($last_names,SORT_DESC,$result);
		//print_r($result);exit;
		foreach ($arr  as $k3 => $so) {
			//高亮 
			if($k3==0) {
				//第一次循环过滤html代码,第二次不能再过滤 否则,高亮会被过滤掉
				foreach ($result  as $k => $v) {
					$cp_list2[$k]['title']= preg_replace("/($so)/i", "<font color=red>\\1</font>", $v['title']);
					//用这个preg_replace函数正则替换关键字,是防止原文 大写字母被替换为小写,改变愿意
					$cp_list2[$k]['xinghao']= preg_replace("/($so)/i", "<font color=red>\\1</font>", $v['xinghao']);
					$cp_list2[$k]['huohao']= preg_replace("/($so)/i", "<font color=red>\\1</font>", $v['huohao']);
					$cp_list2[$k]['description']= preg_replace("/($so)/i", "<font color=red>\\1</font>", $v['description']);
					$cp_list2[$k]['mycontent']= preg_replace("/($so)/i", "<font color=red>\\1</font>", strip_tags($v['mycontent']));
					//过滤无用html
					$cp_list2[$k]['iss']=$v['iss'];
					$cp_list2[$k]['type']=$v['type'];
					$cp_list2[$k]['kucun']=$v['kucun'];
					$cp_list2[$k]['id']=$v['id'];
					$cp_list2[$k]['ctime']=$v['ctime'];
					$cp_list2[$k]['pic']=$v['pic'];
				}
			} else {
				foreach ($result  as $k => $v) {
					$cp_list2[$k]['title']= preg_replace("/($so)/i", "<font color=red>\\1</font>", $cp_list2[$k]['title']);
					$cp_list2[$k]['xinghao']= preg_replace("/($so)/i", "<font color=red>\\1</font>", $cp_list2[$k]['xinghao']);
					$cp_list2[$k]['huohao']= preg_replace("/($so)/i", "<font color=red>\\1</font>", $cp_list2[$k]['huohao']);
					$cp_list2[$k]['description']= preg_replace("/($so)/i", "<font color=red>\\1</font>", $cp_list2[$k]['description']);
					$cp_list2[$k]['mycontent']= preg_replace("/($so)/i", "<font color=red>\\1</font>", $cp_list2[$k]['mycontent']);
				}
			}
		}
	} else {
		//如果关键字不含有标点空格等,则直接替换,不再重复排序
		foreach ($result  as $k => $v) {
			$cp_list2[$k]['title']= preg_replace("/($soso)/i", "<font color=red>\\1</font>", $v['title']);
			$cp_list2[$k]['xinghao']= preg_replace("/($soso)/i", "<font color=red>\\1</font>", $v['xinghao']);
			$cp_list2[$k]['huohao']= preg_replace("/($soso)/i", "<font color=red>\\1</font>", $v['huohao']);
			$cp_list2[$k]['description']= preg_replace("/($soso)/i", "<font color=red>\\1</font>", $v['description']);
			$cp_list2[$k]['mycontent']= preg_replace("/($soso)/i", "<font color=red>\\1</font>", strip_tags($v['mycontent']));
			$cp_list2[$k]['iss']=$v['iss'];
			$cp_list2[$k]['type']=$v['type'];
			$cp_list2[$k]['kucun']=$v['kucun'];
			$cp_list2[$k]['id']=$v['id'];
			$cp_list2[$k]['ctime']=$v['ctime'];
			$cp_list2[$k]['pic']=$v['pic'];
		}
	}
	// 分页
	$count = count($cp_list2);
	$Page  = new \Think\Page($count, 12);
	$show       = $Page->show();
	$cp_list2 = array_splice(array_splice($cp_list2, $Page->firstRow), 0,12);
	//从数组中移除元素,并用新元素取代它:
	//$page->firstRow是列表起始行数,$page->listRows是列表每页显示行数,
	$this->assign('page',$show);//防止与其它地方的page重复.一个页面只能一个分页
	// 下面是对分类名的搜索.最后拼接固定在商品搜索的下面.内容少,无需分页
	$px='px desc,ctime desc';
	//这里可以直接select查询,因为不需要分页
	$cp_class = $this->mypage_soso2('conttype',$cp_class_where,$px,$num=10,$cp_class_where2);
	$cp_class_list=array();
	foreach ($cp_class as $k => $v) {
		$cp_class_list[$k]['id']=$v['id'];
		$cp_class_list[$k]['name']=preg_replace("/($soso3)/i", "<font color=red>\\1</font>",strip_tags($v['name']));
		$cp_class_list[$k]['content']=preg_replace("/($soso3)/i", "<font color=red>\\1</font>",strip_tags($v['content']));
		$cp_class_list[$k]['pic']=$v['pic'];
		$cp_class_list[$k]['pic2']=$v['pic2'];
		$cp_class_list[$k]['ctime']=$v['ctime'];
		$cp_class_list[$k]['dengji']=getcp_class_dengji($v['id']);
	}
	$this->cp_list=$cp_list2;
	$this->cp_class_list=$cp_class_list;
	$this->display();
}

  public function mypage_soso2($mydb,$map,$px,$num=10,$map2){
     //  $count      = M($mydb)->where($map)->count();// 查询满足要求的总记录数
      //  $Page       = new \Think\Page($count,$num);// 实例化分页类 传入总记录数和每页显示的记录数(25)
       // foreach($map2 as $key=>$val) {
        //    $Page->parameter[$key]   =  $val;
       // }
       // $show       = $Page->show();
        $list = M($mydb)->where($map)->order($px)->limit('0,19')->select();
       // $this->assign('page',$show);//注意这里的page可能与上面的商品分页重复,需要单独定义,或栏目搜索直接显示,不要分页,直接注释掉
       // $this->assign('count',$count);
        return $list;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值