Elasticsearch在站内搜索的使用
1.elasticSearch 、solar与luence的区别
Lucene是一套信息检索工具包,并不包含搜索引擎系统,它包含了索引结构、读写索引工具、相关性工具、排序等功能,因此在使用Lucene时仍需要关注搜索引擎系统,例如数据获取、解析、分词等方面的东西。而solr和elasticsearch都是基于该工具包做的一些封装。
Solr是一个有HTTP接口的基于Lucene的查询服务器,封装了很多Lucene细节,自己的应用可以直接利用诸如 .../solr?q=abc 这样的HTTP GET/POST请求去查询,维护修改索引。
Elasticsearch也是一个建立在全文搜索引擎 Apache Lucene基础上的搜索引擎。采用的策略是分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。
solr利用zookpper进行分布式管理,而elasticsearch自身带有分布式协调管理功能;
solr比elasticsearch实现更加全面,solr官方提供的功能更多,而elasticsearch本身更注 重于核心功能,高级功能多由第三方插件提供;
solr在传统的搜索应用中表现好于elasticsearch,而elasticsearch在实时搜索应用方面比solr表现好!
3. Elasticsearch的适用场景
(1)维基百科,类似百度百科,牙膏,牙膏的维基百科,全文检索,高亮,搜索推荐
(2)The Guardian(国外新闻网站),类似搜狐新闻,用户行为日志(点击,浏览,收藏,评论)+社交网络数据(对某某新闻的相关看法),数据分析,给到每篇新闻文章的作者,让他知道他的文章的公众反馈(好,坏,热门,垃圾,鄙视,崇拜)
(3)Stack Overflow(国外的程序异常讨论论坛),IT问题,程序的报错,提交上去,有人会跟你讨论和回答,全文检索,搜索相关问题和答案,程序报错了,就会将报错信息粘贴到里面去,搜索有没有对应的答案
(4)GitHub(开源代码管理),搜索上千亿行代码
(5)电商网站,检索商品
(6)日志数据分析,logstash采集日志,ES进行复杂的数据分析(ELK技术,elasticsearch+logstash+kibana)
(7)商品价格监控网站,用户设定某商品的价格阈值,当低于该阈值的时候,发送通知消息给用户,比如说订阅牙膏的监控,如果高露洁牙膏的家庭套装低于50块钱,就通知我,我就去买
(8)BI系统,商业智能,Business Intelligence。比如说有个大型商场集团,BI,分析一下某某区域最近3年的用户消费金额的趋势以及用户群体的组成构成,产出相关的数张报表,**区,最近3年,每年消费金额呈现100%的增长,而且用户群体85%是高级白领,开一个新商场。ES执行数据分析和挖掘,Kibana进行数据可视化国内
(9)国内:站内搜索(电商,招聘,门户,等等),IT系统搜索(OA,CRM,ERP,等等),数据分析(ES热门的一个使用场景)
3.Elasticsearch入门
国内下载地址: https://thans.cn/mirror/elasticsearch.html
启动:./bin/elasticsearch
如果一切正常,Elastic 就会在默认的9200端口运行。这时,打开另一个命令行窗口,请求该端口,会得到说明信息。
其中elasticsearch.yum配置
cluster.name: elasticsearch
network.host: 0.0.0.0
http.port: 9200
安装中文分词:
https://www.cnblogs.com/ilovepython/p/11650139.html
IK分词器有两种分词模式:ik_max_word和ik_smart模式。
1、ik_max_word
会将文本做最细粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。
2、ik_smart
会做最粗粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。
程序中指定分词
@Document(indexName = "orders", type = "product")
@Mapping(mappingPath = "essearch/productIndex.json") // 解决IK分词不能使用问题
public class ProductDocument extends BaseDocument {
private static final long serialVersionUID = 1L;
private String productName;
private String productDesc;
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductDesc() {
return productDesc;
}
public void setProductDesc(String productDesc) {
this.productDesc = productDesc;
}
}
{
"properties": {
"createTime": {
"type": "long"
},
"productDesc": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"productName": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"updateTime": {
"type": "long"
}
}
}
搜索逻辑实现
@Service
public class BaseSearchServiceImpl<T> implements BaseSearchService<T> {
@Resource
protected ElasticsearchTemplate elasticsearchTemplate;
@Override
public List<T> query(String keyword, Class<T> clazz) {
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(new QueryStringQueryBuilder(keyword))
.withSort(SortBuilders.scoreSort().order(SortOrder.DESC))
.build();
return elasticsearchTemplate.queryForList(searchQuery,clazz);
}
/**
* 高亮显示
*/
@Override
public List<Map<String,Object>> queryHit(String keyword,String indexName,String ... fieldNames) {
// 构造查询条件,使用标准分词器.
QueryBuilder matchQuery = createQueryBuilder(keyword,fieldNames);
// 设置高亮,使用默认的highlighter高亮器
HighlightBuilder highlightBuilder = createHighlightBuilder(fieldNames);
// 设置查询字段
SearchResponse response = elasticsearchTemplate.getClient().prepareSearch(indexName)
.setQuery(matchQuery)
.highlighter(highlightBuilder)
.setSize(10000) // 设置一次返回的文档数量,最大值:10000
.get();
// 返回搜索结果
SearchHits hits = response.getHits();
return getHitList(hits);
}
/**
* 高亮显示,返回分页
*/
@Override
public Page<Map<String, Object>> queryHitByPage(int pageNo,int pageSize, String keyword, String indexName, String... fieldNames) {
// 构造查询条件,使用标准分词器.
QueryBuilder matchQuery = createQueryBuilder(keyword,fieldNames);
// 设置高亮,使用默认的highlighter高亮器
HighlightBuilder highlightBuilder = createHighlightBuilder(fieldNames);
// 设置查询字段
SearchResponse response = elasticsearchTemplate.getClient().prepareSearch(indexName)
.setQuery(matchQuery)
.highlighter(highlightBuilder)
.setFrom((pageNo-1) * pageSize)
.setSize(pageNo * pageSize) // 设置一次返回的文档数量,最大值:10000
.get();
// 返回搜索结果
SearchHits hits = response.getHits();
Long totalCount = hits.getTotalHits();
Page<Map<String, Object>> page = new Page<>(pageNo,pageSize,totalCount.intValue());
page.setList(getHitList(hits));
return page;
}
/**
* 构造查询条件
*/
private QueryBuilder createQueryBuilder(String keyword, String... fieldNames){
// 构造查询条件,使用标准分词器.
return QueryBuilders.multiMatchQuery(keyword,fieldNames) // matchQuery(),单字段搜索
.analyzer("ik_max_word")
.operator(Operator.OR);
}
/**
* 构造高亮器
*/
private HighlightBuilder createHighlightBuilder(String... fieldNames){
// 设置高亮,使用默认的highlighter高亮器
HighlightBuilder highlightBuilder = new HighlightBuilder()
// .field("productName")
.preTags("<span style="color:red">")
.postTags("</span>");
// 设置高亮字段
for (String fieldName: fieldNames) highlightBuilder.field(fieldName);
return highlightBuilder;
}
/**
* 处理高亮结果
*/
private List<Map<String,Object>> getHitList(SearchHits hits){
List<Map<String,Object>> list = new ArrayList<>();
Map<String,Object> map;
for(SearchHit searchHit : hits){
map = new HashMap<>();
// 处理源数据
map.put("source",searchHit.getSourceAsMap());
// 处理高亮数据
Map<String,Object> hitMap = new HashMap<>();
searchHit.getHighlightFields().forEach((k,v) -> {
String hight = "";
for(Text text : v.getFragments()) hight += text.string();
hitMap.put(v.getName(),hight);
});
map.put("highlight",hitMap);
list.add(map);
}
return list;
}
@Override
public void deleteIndex(String indexName) {
elasticsearchTemplate.deleteIndex(indexName);
}
}
实例应用:
https://gitee.com/pengchua/elasticsearch
以上是 Elasticsearch在站内搜索的使用 的全部内容, 来源链接: utcz.com/z/517425.html