迅搜(xunsearch) 多值属性的处理

我之前使用Yii2框架做了一个电影网站dy360.net,网站的搜索是通过MySQL的like实现,搜索的条件很多,担心以后数据越来越多,会拖垮网站的速度,于是想通过搜索引擎来解决! 开始准备使用sphinx,研究发现不太好使。后发现迅搜(xunsearch),文档比较清楚,上手比较简单,并且有Yii2的composer包,于是决定使用迅搜。

使用的过程中遇到这样一个问题:一部电影有多个演员,出品国家或地区,其实就是文档的多值属性的新建、搜索的问题。我研究了一下,最终结局方案如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#项目的配置文件

project.name = yddy
project.default_charset = utf-8
server.index = 8383
server.search = 8384

[id]
type = id
phrase = yes

[summary]
type = body
cutlen=900

[year]
type = numeric
phrase = yes
index = self

[actors_text]
type = string
index = self
tokenizer = split(/)

[category_id]
type = string
index = self
tokenizer = split(,)


[country_id]
type = string
index = self
tokenizer = split(,)
phrase = yes

其实就是使用迅搜的tokenizer分词器,文档上具体的语法如下:

1
2
3
4
5
6
7
8
9
10
11
tokenizer 分词器

默认为 default 采用内置的功能强大的 scws 分词,适合绝大多数字符串字段。也可以指定自定义分词器, 格式为 name 或 name(arg) 两种形式,其中 name 是分词器名称,arg 则是传递给分词器构造函数的参数。 自定义分词器需要在 lib/ 目录下编写名为 XSTokenizerName 的分词类并实现接口 XSTokenizer, 内置支持的分词器有以下几种:

full 表示本字段的值整体作为一个检索词,像各种 ID 都适合这种情况
none 表示本字段没有任何词汇用于索引
split([ ]) 表示根据参数分割内容,默认参数为空格,若参数以 / 开头并以 / 结尾则 内部调用 preg_split(arg, ..) 来分割取词,以支持正则或其它特殊字符分割
xlen([2]) 表示根据指定参数长度分段取词,如 ABCDEF => AB + CD + EF
xstep([2]) 表示根据指定参数步长逐段取词,如 ABCDEF => AB + ABCD + ABCDEF
scws([3]) 表示采用指定参数为复合等级的 scws 分词,(若无特殊复合需求,无需指定)
tokenizer = default

然后,根据不同情况使用不同的分割参数,譬如,有的使用’/‘,有的使用’,’。
最后,搜索代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public static function search($params){
$db = Yii::$app->xunsearch->getDatabase('yddy');
$xs = $db->xs;

$search = $xs->getSearch();

$keywords = $params['word'];
if(empty($keywords)){
$keywords ='';
}
$search = $search->setQuery($keywords);

if($category=$params['category']){
$search->addQueryTerm('category_id',$category);
}
if($country=$params['country']){
$search->addQueryTerm('country_id',$country);
}

if( (empty($params['other']) ) && ($year = intval($params['year'])) && is_numeric($params['year'])){
$search->addQueryTerm('year',$year);

}elseif(($params['other'] == 'ago') && ($year = intval($params['year'])) ){
//$search->addRange('year',1900,1978);
$search->addRange('year',1900,$year);
}

if( $rating=intval($params['rating'])){
$search->addQueryTerm('rate', $rating);
}

$search->addQueryTerm('subtype',$params['subtype']);
//$search->addQueryTerm('status',1);
//echo $search->getQuery();
return $search;

}
  • 作者: Sam
  • 发布时间: 2017-12-04 23:18:36
  • 最后更新: 2019-12-09 23:03:26
  • 文章链接: https://ydstudios.gitee.io/post/10379547.html
  • 版权声明: 本网所有文章除特别声明外, 禁止未经授权转载,违者依法追究相关法律责任!