欢迎分享:http://toutiao.io/contribute
大家知道用like搜索的性能是何其低下,尤其是当关键词前也要加%匹配的时候,即使建立了索引,也要进行全表扫描。当这种搜索的请求比较频繁的时候,数据库就会成为性能瓶颈。 我们熟知的Lucene是一款非常优秀的开源搜索引擎,不过它的使用比较复杂,产生的大量索引文件也不便于管理。 这时不妨试试elasticsearch,它不仅基于lucene,拥有和lucene一样强大的搜索功能,而且为索引文件提供了分布式管理平台,而且大大简化了搜索相关的API。 笔者以一个简单的电商中商品搜索应用为例。首先我们部署好elasticsearch(以下简称ES)。下载链接及安装步骤。 ES有丰富的插件,其中有3个插件是我推荐安装的:
外加一款chrome插件sense。 head是ES的web控制台。ik是中文分词插件,river用来把关系数据库中的数据导入ES,sense是ES的调试工具,可以方便地通过浏览器给ES集群发送各种请求。 ES的简单用法这里就不讲了,直接进入实战。 首先分析商品搜索的需求。一般来说商品搜索分两种,一种是在电商首页的搜索条上敲商品名支持自动补全和联想功能,一种是根据商品名加上其它参数,比如价格区间做模糊匹配。 针对这两种不同的需求,我们需要为商品在ES中建立两个type,类比关系数据库,相当于建两张表,用于自动补全的type称之为keyword_goods,因为主要用于关键字搜索,只要保存关键字和商品ID就可以了,而用于模糊匹配查找的type称为goods,里面要保存商品的各种属性信息,以便支持filter查找。 首先我们创建index和type,在创建时添加mapping和setting如下: mapping: {
"goods": {
"properties": {
"name": {
"type": "string",
"index": "analyzed",
"analyzer": "cn_analyzer"
},
"sn": {
"type": "string",
"index": "not_analyzed"
},
"shop_price": {
"type": "float",
"index": "not_analyzed"
},
"shop_id": {
"type": "long",
"index": "not_analyzed"
},
"cate_id": {
"type": "long",
"index": "not_analyzed"
}
}
}
}
setting: {
"index": {
"analysis": {
"analyzer": {
"cn_analyzer": {
"type" : "custom",
"tokenizer" : "ik"
}
}
}
}
}
在setting里申明使用ik分词器作为cnanalyzer,默认情况下ES使用雪球(snowball)分词器,不支持中文词汇。在mapping中申明对name字段进行cnanalyzer中文分词(其实商品名很短,不需要分词,长文本搜索才用的到,这里只为演示)。mapping中列出商品需要被索引的字段。 在服务器启动的时候检查type是否存在,如果不存在创建type public void createIndice(String mapping, String settings,
String indice, String type) throws Exception {
Client client = searchClient.getClient();
CreateIndexRequest indexRequest = new CreateIndexRequest(indice);
if (mapping != null) {
indexRequest.mapping(type, mapping);
}
if (settings != null) {
indexRequest.settings(settings);
}
client.admin().indices().create(indexRequest).actionGet();
}
@PostConstruct
public void initService() {
log.debug("Initializing search service");
try {
index.init(searchClient);
keyword.init(searchClient);
} catch (Exception e) {
log.error("Cannot initialize SearchService correctly, will be initialized lazily", e);
}
}
说明两点:
这样就类似于JPA的方式,而type就类似于数据库的表而mapping就相当于建表的sql。 当用户插入新的商品时,就要在两个type中建立索引,spring的配置如下: |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|