如何通过幂集分词表构建高效长尾词搜索接口?

2026-04-02 03:221阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计789个文字,预计阅读时间需要4分钟。

如何通过幂集分词表构建高效长尾词搜索接口?

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

思路:

1.通过程序将所有商品信息进行预处理。

2.建立一个快速索引结构,如哈希表或Trie树,以便快速检索。

3.提供接口供前端调用,实现高效的搜索功能。

如何通过幂集分词表构建高效长尾词搜索接口?

前言:

在业务开发中,有一些面向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. 搜索分词表创建。

字段名

类型

描述

id

int

主键 ID

goods_id

int

商品编号

search_path

varchar

分词字符

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

<?php namespace 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; }

本文共计789个文字,预计阅读时间需要4分钟。

如何通过幂集分词表构建高效长尾词搜索接口?

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

思路:

1.通过程序将所有商品信息进行预处理。

2.建立一个快速索引结构,如哈希表或Trie树,以便快速检索。

3.提供接口供前端调用,实现高效的搜索功能。

如何通过幂集分词表构建高效长尾词搜索接口?

前言:

在业务开发中,有一些面向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. 搜索分词表创建。

字段名

类型

描述

id

int

主键 ID

goods_id

int

商品编号

search_path

varchar

分词字符

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

<?php namespace 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; }