阅读 80

sphinx(九)根据关键词相似度排序

全文检索通过sphinx搜索出来的内容是没有问题的。

但是搜索结束之后,文章的排序还是多少有点小问题,是这样,我最开始是使用时间倒叙排序,这样就会有一个小问题就是,我想要的结果,或者说跟我搜索关键词最贴近的结果不会出现在前几条。这个体验很不好。

然后,我这里使用了PHP内置的similar_text函数对文章的描述以及标题进行相似度的计算,然后根据计算之后的相似度数值进行倒叙排序。

我这里封装了一个函数:仅作示例,具体还是需要根据你自己的需求来

function similar_arr($array, $keyword, $arr_key = 'title') {     //数组相似度处理     foreach ($array as $key => $value)      {         similar_text($value[$arr_key], $keyword, $percent);         $value['percent'] = $percent;         $data[] = $value;               }       //取出数组中percent的一列,返回一维数组     $percent =  array_column($data, 'percent');       //排序,根据 percent 排序     array_multisort($percent, SORT_DESC, $data);          return $data; } // $data是一个二维数组 $res = similar_arr($data, '微信小程序'); var_dump($res); 复制代码

这个是没有问题的,但是其对中文的相似度计算不是很友好。有点瞎算的感觉。

这可怎么办呢?也不能用这玩意啊。

百度上还是大婶多,我这里找到了一个计算中文相似度的一个类,我这里稍加改动了一下:

整体如下所示:

Lcscontroller.php

<?php   namespace App\Http\Controllers\index;   /**  * @name: 文章相似度计算类  * @author: camellia  * @date: 2021-03-04   */ class LcsController extends BaseController {     private $str1;     private $str2;     private $c = array();     /**      * @name: 返回串一和串二的最长公共子序列      * @author: camellia      * @date: 2021-03-04       * @param:  data    type    description      * @return: data    type    description      */     public function getLCS($str1, $str2, $len1 = 0, $len2 = 0)     {         $this->str1 = $str1;         $this->str2 = $str2;         if ($len1 == 0) $len1 = strlen($str1);         if ($len2 == 0) $len2 = strlen($str2);         $this->initC($len1, $len2);         return $this->printLCS($this->c, $len1 - 1, $len2 - 1);     }     /**      * @name: 返回两个串的相似度      * @author: camellia      * @date: 2021-03-04       * @param:  data    type    description      * @return: data    type    description      */     public function getSimilar($str1, $str2)     {         $len1 = strlen($str1);         $len2 = strlen($str2);         $len = strlen($this->getLCS($str1, $str2, $len1, $len2));         if(($len1 + $len2) > 0)         {             return $len * 2 / ($len1 + $len2);         }         else         {             return 0;         }              }     /**      * @name: 函数名      * @author: camellia      * @date: 2021-03-04       * @param:  data    type    description      * @return: data    type    description      */     public function initC($len1, $len2)     {         for ($i = 0; $i < $len1; $i++)          {             $this->c[$i][0] = 0;         }         for ($j = 0; $j < $len2; $j++)          {             $this->c[0][$j] = 0;         }         for ($i = 1; $i < $len1; $i++)          {             for ($j = 1; $j < $len2; $j++)              {                 if ($this->str1[$i] == $this->str2[$j])                  {                     $this->c[$i][$j] = $this->c[$i - 1][$j - 1] + 1;                 }                  else if ($this->c[$i - 1][$j] >= $this->c[$i][$j - 1])                  {                     $this->c[$i][$j] = $this->c[$i - 1][$j];                 }                  else                  {                     $this->c[$i][$j] = $this->c[$i][$j - 1];                 }             }         }     }     /**      * @name: 函数名      * @author: camellia      * @date: 2021-03-04       * @param:  data    type    description      * @return: data    type    description      */     public function printLCS($c, $i, $j)     {         if($i < 0 || $j < 0)         {             return "";         }         if ($i == 0 || $j == 0)          {             if ($this->str1[$i] == $this->str2[$j])              {                 return $this->str2[$j];             }             else              {                 return "";             }         }         if ($this->str1[$i] == $this->str2[$j])          {             return $this->printLCS($this->c, $i - 1, $j - 1) . $this->str2[$j];         }         else if ($this->c[$i - 1][$j] >= $this->c[$i][$j - 1])          {             return $this->printLCS($this->c, $i - 1, $j);         }          else          {             return $this->printLCS($this->c, $i, $j - 1);         }     } } 复制代码

调用:

 /**      * @name: 根据相似度对数组进行排序      * @author: camellia      * @date: 2021-03-04       * @param:  data    type    description      * @return: data    type    description      */     public function similar_arr($array, $keyword, $arr_key_one = 'arttitle', $arr_key_two='content', $arr_key_three= 'artdesc')     {         $lcs = new LcsController();           //数组相似度处理         foreach ($array as $key => $value) {             // similar_text函数对中文相似度处理的不是很友好             // similar_text($value[$arr_key], $keyword, $percent);             $title_percent = $lcs->getSimilar($value[$arr_key_one], $keyword);             //返回最长公共子序列             //echo $lcs->getLCS("hello word","hello china");             $value['title_percent'] = $title_percent;             // $content_percent = $lcs->getSimilar($value[$arr_key_two], $keyword);             // $value['content_percent'] = $content_percent;             $desc_percent = $lcs->getSimilar($value[$arr_key_three], $keyword);             $value['desc_percent'] = $desc_percent;             $data[] = $value;         }           //取出数组中percent的一列,返回一维数组         // $percent = array_column($data, 'percent');         //排序,根据 percent 排序         // array_multisort($percent, SORT_DESC, $data);         // $array = $this->sortArrByManyField($data, 'title_percent', SORT_DESC, 'content_percent', SORT_DESC, 'desc_percent', SORT_DESC);         $array = $this->sortArrByManyField($data, 'title_percent',SORT_DESC, 'id', SORT_DESC, 'desc_percent', SORT_DESC );         return $array;     }     /**      * @name: php二维数组根据多个字段排序      * @author: camellia      * @date: 2021-03-04       * @param:  data    type    description      * @return: data    type    description      */     public function sortArrByManyField()     {         $args = func_get_args(); // 获取函数的参数的数组         if(empty($args))         {             return null;         }         $arr = array_shift($args);         if(!is_array($arr))         {             throw new Exception("第一个参数不为数组");         }         foreach($args as $key => $field)         {             if(is_string($field)){             $temp = array();             foreach($arr as $index=> $val){                 $temp[$index] = $val[$field];             }             $args[$key] = $temp;             }         }         $args[] = &$arr;//引用值         call_user_func_array('array_multisort',$args);         return array_pop($args);     } 复制代码

调用计算相似度方法

 $listShow = $this->similar_arr($list, $search, 'arttitle'); 复制代码

这个最后的计算出来的相似度其实也不是特别的精确,但是,要比PHP内置的similar_text函数要好。


作者:camellia
链接:https://juejin.cn/post/7026434799455698980


文章分类
前端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐