ElasticSearch中文分词和模糊查询

前言

        ElasticSearch是一个一个分布式的实时文档存储,每一个字段都可以被索引与搜索,并且能支持PB级别的结构化或者非结构化数据。早期我们应用的全局搜索是简单的SQL模糊查询,为了分担数据库压力所以用了ES,选择他的原因除了以上几点外,还有其提供的API方式简单,于任何对接的编程语言都适用。以下将以PHP的业务场景完善搜索功能。

环境

ThinkPHP5.1

ElasticSearch7.8

PHP7.3

功能迭代简介

        最开始的ES取代方法解决了搜索速度问题,后来新增的ik分词器,解决了搜索词条单一问题。单也正是中文分词原因,对每句话都是拆解成指定粒度的词。当遇到单词时,一般只会对一句话里的单词进行拆解,而搜索时需要输入某个字母,希望输出的是带字母后面的词条,也就是模糊查询。经过翻阅文档,发现了即时搜索。

       即时搜索或输入即搜索(search-as-you-type),就是当用户习惯在输完查询内容之前,就能为他们展现搜索结果,不仅能在更短的时间内得到搜索结果,也能引导用户搜索索引中真实存在的结果。例如,输入 dvd r ,即时搜索会得到:dvd r9s 和 dvd r9sk等 , 以下将通过完整示例演示效果。

配置索引的映射

        关于ElasticSearch环境搭建和基本操作在前面文章有说明,这里就假装已经创建了索引,以下是索引的映射。还有文档的添加也是根据你自己的需求定义了,不管是定时任务还是业务节点触发,亦或是采集工具同步等。

{
  "mappings": {
    "_doc": {
      "properties": {
        "class_id": {
          "type": "long"
        },
        "goods_name": {
          "type": "text",
          "analyzer": "ik_smart"
        },
        "goods_sort": {
          "type": "keyword"
        },
        "id": {
          "type": "keyword"
        },
        "price": {
          "type": "long"
        },
        "single_goods_name": {
          "type": "text",
          "analyzer": "ik_max_word"
        },
        "state": {
          "type": "keyword"
        },
        "v": {
          "type": "long"
        }
      }
    }
  }
}

前台搜索

1.  即搜索示例

{
    "match_phrase_prefix" : {
        "brand" : {
            "query": "walker johnnie bl", 
            "slop":  10
        }
    }
}

2. 业务代码

public function queryData($key, $sort, $from = 0, $size = 10)
{
	$from = $from * $size;
	$indexName = Env::get('elasticsearch.goods_index') ?? 'products';

	$params = [
		'index' => $indexName,
		'client' => [
			'timeout' => 10,        
			'connect_timeout' => 10
		],
		'body' => [
			'from' => $from,
			'size' => $size,
			'query' => [
				'bool' => [
					'should' => [
						[
							'multi_match' => [
								'query' => $key,
								'fields' => [
									'goods_name^2',
									'single_goods_name'
								],
							],
						],
						[
							'wildcard' => [
								'single_goods_name' => "$key*"
							]
						],
						[
							'fuzzy' => [
								'single_goods_name' => [
									'value' => $key
								]
							]
						],
						[
							'match_phrase_prefix' => [
								'single_goods_name' => "$key"
							]
						],
					],
				],
			],
			'sort' => [
				['_score' => "desc"],
				['goods_sort' => 'desc']
			],
		]
	];

	return $this->es->search($params);
}

3. 效果演示

猜你喜欢

转载自blog.csdn.net/qq_35704550/article/details/130575506