写点什么

搜索接口优化方案——幂集分词表

作者:北桥苏
  • 2023-05-12
    广东
  • 本文字数:1807 字

    阅读完需:约 6 分钟

前言:

在业务开发中,有一些面向 C 端的搜索接口。比如根据商品名搜索,之前也提过通过 ES 解决,但这次主要以一种较为简单快捷的方式优化搜索速度。



思路:

\1. 通过程序将所有商品名进行分词并幂集组合。\2. 将所有商品名称幂集存入一张单独的表中。\3. 每个分词对应一个商品 ID。\4. 搜索关键词对幂集表的分词模糊查询并取出商品 ID。\5. 对应的商品 ID 就是搜索出来的商品。


编码:

\1. 数组元素的幂集函数。


if (!function_exists('powerSet')) {
function powerSet($array) {
$results = array(array());
foreach ($array as $element) {
foreach ($results as $combination) {
$results[] = array_merge(array($element), $combination);
}
}
return array_values($results); }}
复制代码


\2. 搜索分词表创建。




\3. 生成搜索词数据命令, 以后可通过 php think make:name 执行。


<?phpnamespace app\common\command;
use think\console\Command;use think\console\Input;use think\console\input\Argument;use think\console\input\Option;use think\console\Output;
use think\Db;

class MakeName extends Command{
protected function configure(){
$this->setName('make:name'); }
protected function execute(Input $input, Output $output){

ini_set ('memory_limit', '512M');
$output->info("===========BEGIN===========");

$goods = Db::name("goods")->where("class_id",2)->cursor();
foreach ($goods as $goods_value) {
$output->info("===========".$goods_value['goods_name']."===========");
$goods_name = strtolower($goods_value['goods_name']);
$name_array = explode(" ", $goods_name); $list = powerSet($name_array);
$path = [];
foreach ($list as $value) {
if(!count($value)) continue;
$temp = array_reverse($value);
$data['goods_id'] = $goods_value['id']; $data['search_path'] = implode("",$temp); $path[] = $data; $output->writeln($data['search_path']); unset($data); }

Db::name("search")->where("goods_id",$goods_value['id'])->delete();
Db::name("search")->insertAll($path);
unset($path); }
$output->info("===========END==========="); }}
复制代码


\4. 搜索功能方法示例。


/** * @Notes: * @param string $keyWord 搜索关键字 * @param int $page 页码 * @param int $size 每页数量 * @return array */public function search($keyWord = '', $page = 1, $size = 10){    $where = [];    $where[] = $keyWord . '%';    $where[] = str_replace(" ", "", $keyWord) . '%';    $keyArr = explode(" ", $keyWord);    foreach ($keyArr as $value) {        $where[] = trim($value) . '%';    }
$ids = Db::name("search")->where("search_path", "like", $where, "OR")->column("goods_id");
$ids = array_unique($ids);
$goods = 0; $goods = Db::name("goods")->where("state", 1)->where("goods_name", "=", $keyWord)->value("id"); if ($goods && $page == 1) {
$key = array_search($goods, $ids); unset($ids[$key]); }
$map[] = ['state', '=', 1]; $map[] = ['delete_time', '=', 0]; $map[] = ['id', 'in', $ids];
$res = self::where($map)->field("id,goods_name")->order(['sort' => 'desc', 'id' => 'desc'])->page($page, $size)->select()->toArray();
if ($goods && $page == 1) { if ($res) { $first = $res[0]; $res[0] = ['id' => $goods, 'goods_name' => $keyWord]; $res[] = $first; } else { $res[0] = ['id' => $goods, 'goods_name' => $keyWord]; }
} return $res;}
复制代码



用户头像

北桥苏

关注

公众号:ZERO开发 2023-05-08 加入

专注后端实战技术分享,不限于PHP,Python,JavaScript, Java等语言,致力于给猿友们提供有价值,有干货的内容。

评论

发布
暂无评论
搜索接口优化方案——幂集分词表_php_北桥苏_InfoQ写作社区