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

简介: 全文检索通过sphinx搜索出来的内容是没有问题的。这里使用了PHP内置的similar_text函数对文章的描述以及标题进行相似度的计算,然后根据计算之后的相似度数值进行倒叙排序。

QQ图片20220425164205.jpg

全文检索通过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函数要好。



目录
相关文章
|
4月前
|
存储 SQL 测试技术
使用ClickHouse进行向量搜索 - 第二部分
本文介绍了如何使用ClickHouse进行向量搜索。总体来说,本文通俗易懂地介绍了如何使用ClickHouse进行向量搜索,包括概念、实现、高级功能和应用示例,对使用ClickHouse进行向量搜索提供了很好的概述。
51336 18
|
1月前
|
机器学习/深度学习 人工智能 算法
如何将传统的关键字搜索与现代向量搜索结合?
如何将传统的关键字搜索与现代向量搜索相结合,找到更相关的搜索结果优化 RAG。
如何将传统的关键字搜索与现代向量搜索结合?
|
2月前
|
人工智能 自然语言处理 开发工具
关键词感知检索
向量检索服务DashVector同时支持Dense Vector(稠密向量)和Sparse Vector(稀疏向量),前者用于模型的高维特征(Embedding)表达,后者用于关键词和词频信息表达。DashVector可以进行关键词感知的向量检索,即Dense Vector和Sparse Vector结合的混合检索。
关键词感知检索
|
3月前
|
自然语言处理 开发工具 索引
向量检索服务——关键词感知检索详解
向量检索服务DashVector同时支持Dense Vector(稠密向量)和Sparse Vector(稀疏向量),前者用于模型的高维特征(Embedding)表达,后者用于关键词和词频信息表达。DashVector可以进行关键词感知的向量检索,即Dense Vector和Sparse Vector结合的混合检索。
|
9月前
|
自然语言处理 数据处理 Python
|
11月前
|
SQL Java
白话Elasticsearch04- 结构化搜索之使用terms query搜索多个值以及多值搜索结果优化
白话Elasticsearch04- 结构化搜索之使用terms query搜索多个值以及多值搜索结果优化
460 0
|
2天前
|
算法 关系型数据库 分布式数据库
0 PolarDB 开源版通过pg_similarity实现17种文本相似搜索 - token归一切分, 根据文本相似度检索相似文本
背景PolarDB 的云原生存算分离架构, 具备低廉的数据存储、高效扩展弹性、高速多机并行计算能力、高速数据搜索和处理; PolarDB与计算算法结合, 将实现双剑合璧, 推动业务数据的价值产出, 将数据变成生产力.本文将介绍PolarDB 开源版通过pg_similarity实现17种文本相似搜索...
|
存储 并行计算 算法
PolarDB 开源版通过pg_similarity实现17种文本相似搜索 - token归一切分, 根据文本相似度检索相似文本.
PolarDB 的云原生存算分离架构, 具备低廉的数据存储、高效扩展弹性、高速多机并行计算能力、高速数据搜索和处理; PolarDB与计算算法结合, 将实现双剑合璧, 推动业务数据的价值产出, 将数据变成生产力. 本文将介绍PolarDB 开源版通过pg_similarity实现17种文本相似搜索 - token归一切分, 根据文本相似度检索相似文本.
507 0
|
SQL 人工智能 自然语言处理
【Solr】之使用结巴分词模拟搜索商品1
【Solr】之使用结巴分词模拟搜索商品1
100 0
【Solr】之使用结巴分词模拟搜索商品1
|
机器学习/深度学习 搜索推荐 数据处理
这就是搜索引擎读书笔记-day3-5.检索模型与搜索排序
搜索结果排序融合了上百种排序因子,而重要两因素是:用户查询和网页内容相关性 及 网页链接情况。本节介绍内容相关性介绍网页排序
这就是搜索引擎读书笔记-day3-5.检索模型与搜索排序