ThinkPHP5 使用迅搜 (XunSearch) 实现全文检索实例指导

2024-06-07 17:08

本文主要是介绍ThinkPHP5 使用迅搜 (XunSearch) 实现全文检索实例指导,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前期准备

入坑了一天,折腾的无语,个人观点:【文档太差,适合学习思路,小心入坑】

  • 背景

    最近在整理全文检索解决方案
    注意到 PHP 环境中对 xunsearch 的评价很高,在此记录一番

【Xunsearch 是一个高性能、全功能的全文检索解决方案】

  • 场景描述

    此处作为对 xunsearch 的初次使用,
    以一个简单的商品 SKU 信息搜索场景进行描述
    我已有一张 tp5_xsku表,用来存储商品 SKU 信息
    主键为 "sku_id",需要进行匹配的字段为:"spec_name"

  • 环境

PHP:	php7.2.9
Linux:	CentOS7.9
MySQL:	mysql5.7.32

XunSearch 服务端搭建

  • 此处,我将网站应用部署在本地 windows 环境
    然后,使用一台虚拟机 【192.168.80.224】作为 xunsearch 服务器的部署环境

官方指导文档 —— 【安装、升级 Xunsearch】

1). 运行下面指令下载、解压安装包

  • 此处,我选择的是一台 CentOS7 的虚拟机 [ip:192.168.80.224],作为服务端
wget http://www.xunsearch.com/download/xunsearch-full-latest.tar.bz2
tar -xjf xunsearch-full-latest.tar.bz2

2). 执行安装脚本

  • 首先,建议将解压后的文件夹移动到 "usr/local/" 目录下
    此处,我做了文件夹重命名、拷贝操作
mv xunsearch-full-1.4.15/ xunsearch
cp -r xunsearch /usr/local/xunsearch
  • 然后执行安装脚本命令
    选择默认即可(第一次安装的话,过程可能会稍显漫长)
cd /usr/local/xunsearch/
sh setup.sh
  • 一般没啥问题,最终成功提示信息如下:

因为我的 SDK 调用和 xunsearch 服务端 不在同一服务器,所以使用 "-b inet" 方式启动脚

/usr/local/xunsearch/bin/xs-ctl.sh -b inet start

【提示】:

  • 注意官方建议的 不同启动方式,不然坑死你
    其次,测试发现,如果我直接删掉了 "/usr/local/xunsearch/data" 文件夹,后续直接没反应
    需要重启 xunsearch 服务方可!(也没见官网提示
    不过,只是删除 "/usr/local/xunsearch/data/" 内的文件夹,是无需重启的!

3). 设置端口号

  • 通过对 xunsearch 的启动命令操作发现,需要有端口号 "8383、8384" 的支持
    注意借助类似 iptables 的防火墙,
    来控制 xunsearch8383/8384 两个端口的访问权限
  • 启动完成后,可以输入命令查看服务的运行状态: "ps -ef | grep xs-searchd"
[root@localhost ~]# ps -ef | grep xs-searchd
root       2431      1  0 13:25 ?        00:00:00 xs-searchd: master
root       2432   2431  0 13:25 ?        00:00:00 xs-searchd: worker[1]
root       2433   2431  0 13:25 ?        00:00:00 xs-searchd: worker[2]
root       2434   2431  0 13:25 ?        00:00:00 xs-searchd: worker[3]
root       2487   2397  0 13:29 pts/0    00:00:00 grep --color=auto xs-searchd

4). 设置开机启动

建议将 xunsearch 添加到开机启动脚本中,以便每次服务器重启后能自动启动搜索服务程序

  • Linux 系统中,
    可以将脚本指令 "/usr/local/xunsearch/bin/xs-ctl.sh -b inet start"
    写进 "/etc/rc.local" 文件,然后保存退出即可
vi /etc/rc.local

提示: 本机测试,开机重启不成功,这就尴尬了!!!


ThinkPHP5 应用框架的配置

此处,注意,应用框架跟前面的 "XunSearch" 服务端不在一个 ip 地址

1). composer 安装 sdk

官方指导文档 —— 【通过Composer 使用 Xunsearch SDK】

  • 进入项目根目录,执行 composer 指令如下:
composer require --prefer-dist hightman/xunsearch "*@beta"
  • 此时,会在 "vendor" 目录下,生成两个相关文件夹
  • 检测 PHP-SDK 的运行条件
    此时,可以在 "vendor\hightman\xunsearch\util" 目录中
    运行 php 指令:php RequiredCheck.php

2). 配置文件的修改

对于配置文件的详细解释,建议阅读文档 —— 【xunsearch 项目配置文件详解】

每个搜索项目必须有且仅有一个 type=id 字段,确保每条数据具备唯一值,是索引更新和删除的凭据

  • 可以参考 "vendor/hightman/xunsearch/app/demo.ini" 文件
    创建属于自己业务的配置文件
    我新建了一个"goods_sku.ini" 文件,配置参考如下:
project.name = goods_sku
project.default_charset = utf-8
server.index = 192.168.80.224:8383
server.search = 192.168.80.224:8384[sku_id]
type = id[spec_name]
type = string
index = both

3). 集成方法类 "XunseachService" 的使用

根据网上的一些经验,建议,创建一个集成方法类

  • 此处,提供 "XunsearchService.php" 的源码,方便参考使用
<?phpnamespace app\common\lib;
/*** xunsearch 集成使用类* Class XunsearchService* @package app\common\lib*/
class XunsearchService
{/*** 中文分词搜索* @param string $keywords 关键词* @param string $file ini文件名* @param bool $is_scws 是否开启中文分词(例如:口袋新世代,拆分成:口袋、新、世代)* @param int $limit 搜索结果条数* @return array 返回结果* @throws \XSException*/public static function search($keywords,$file = 'demo',$is_scws = false,$limit = 100){$xs = new \XS($file);if($is_scws === true) {//中文分词$tokenizer = new \XSTokenizerScws;//词语拆分$words = $tokenizer->getTokens($keywords);$where = '';//拼接成查询条件(OR)foreach ($words as $key => $val) {if ($key == 0) {$where = $val;} else {$where .= ' OR ' . $val;}}}else {$where = $keywords;}$search = $xs->search;$result =  $xs->search->setQuery($where)//->setSort('sku_id','asc') #按索引排序->setDocOrder(true) #按添加索引排序(升序)->setLimit($limit)->search();$search->close();return $result;}/***  新增/更新/删除 xunsearch 数据库* @param array $data* @param string $file ini文件名* @param string $tag 'add':新增;'update':更新;'[主键ID]':删除* @return bool*/public function save($data,$file = 'demo',$tag = 'add'){try {$xs = new \XS($file);#创建文档对象$doc = new \XSDocument;$doc->setFields($data);#更新(新增)数据$index = $xs->index;if ($tag == 'add'){$index->add($doc);}elseif ($tag == 'update'){$index->update($doc);}else{// 此处,传来的是作为主键的值$index->del($tag);}#强制刷新当前索引列表数据return $index->flushIndex();}catch (\Exception $e){return false;}}
}

新建类名可自定义,基本没啥疑问

4). 增加索引的操作

  • 在商品 SKU 数据操作变化的业务逻辑位置,添加如下代码:
    (注意传参的不同,此处只是演示了增加的操作)
$xs_data = ['sku_id' => $sku_ID,'spec_name' => $spec_name];
$xsService = new XunsearchService();
$xsService::save($xs_data,'goods_sku');

提示

  • 如果操作成功,你会在 xunsearch服务端的 "data"目录下发现一个 "goods_sku" 的文件夹

5). 索引查询操作

  • 在需要进行查询操作的位置,补充如下代码:
    (后续便是根据返回的数组,然后匹配业务数据表的 sku_id ,进行商品信息的展示了 …)
$xsService = new XunsearchService();
try {$message = $xsService::search('我找原味的瓜子和爆款蓝牙', 'goods_sku', true);} catch (\XSException $e) {$message = $e->getMessage();}var_dump($message);

☞ 附录

①. 代码检索测试

  • 首先,我触发"$xsService->save()" 事件,得到了六个数据
    然后,在查询操作时,置空 "$xsService::search()" 的第一个参数可得到如下数据:
  • 在此,我设置查询的文字为:"我找原味的瓜子和爆款蓝牙"
    代码处理,得到的查询语句为:"我找 OR 找 OR 原味 OR 的 OR 瓜子 OR 和 OR 和爆 OR 爆款 OR 款 OR 蓝牙"
    运行匹配得到的结果集如下:

从结果上来看,还是可以接受的

不过,此处可以注意到拆分的名词还是差点意思,可对比参考下 —— 【HanLP 在线演示】

②. 全文检索应用场景

  • 首先,再次明确一下 “全文检索” 概念
  创建索引,然后查询索引的过程我们称之为全文检索,索引一次创建可以多次使用,这样就不用了每一次都进行文件数据查分,比较快
  • 其次便是 “全文检索” 的应用场景
  1. 搜索引擎:百度,360,谷歌等等2. 站内搜索:论坛搜索评论,微博搜索热点,新闻网站搜索新闻3. 电商搜索:淘宝,京东

有搜索的地方都可以用到全文检索

  • 举一个我们电商项目中的场景
  小程序首页提供商品搜索功能设计时,需要满足:有足够商品时就显示商品不够时,也可以展示相关文章那么设计思路如下:1. 在商品添加时,就将 goods_id,goods_name,type=1(标记为商品) 添加到 xunsearch 索引文档中2. 同时,在添加文章时,将 article_id,title,type=2(标记为文章) 也添加到 xunsearch 索引文档中3. 用户在首页输入信息时,触发 search 查询事件4. 在 search 查询事件中,定义按照 type 升序获取前 20 条记录然后,根据数据匹配数据库中的 商品及文章(图片/标题/主键ID)最终,在前端的搜索列表中展示出来满足用户点击后,直接进入对应的详情页面

补充:

  • 可以参考百度搜索的结果:将得到的信息,使用正则表达式 高亮显示匹配的词汇
  • 注意,对存在索引的更新、删除操作,避免冗余数据的产生
    后期根据自己的业务需求进行拓展 …

③. 一点点拙见

提示: 目测官方没有好的精力去升级优化,论坛也没法访问,好多问题找不到探讨 ...

  • 忍不住吐槽

    学习过程中
    网上的例子比较少,遇到问题不好解答
    比较失望的是,官方文档说的不清楚,需要多次测试,碰运气的感觉
    好歹给个参考实例,演示代码实现过程吧!!

  • 再给个赞赏

    话又说回来
    作为开源项目为大家提供便利
    本身就是值得赞赏的,太过吹毛求疵就不好了!

希望,同道中人少踩几个坑,共同进步,谢谢 ...

这篇关于ThinkPHP5 使用迅搜 (XunSearch) 实现全文检索实例指导的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1039776

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo