后端:使用Elasticsearch实现商品搜索。
前端:使用Vue对查询的商品列表进行展示。
通过TransportClient发起对ES(Elasticsearch的简称)的索引创建、关键词查询等功能。
1. 在工程的POM.xm文件中添加相关依赖Jar包。
在父级工程中,添加TransportClient的版本管理:
org.elasticsearch.client
transport
5.5.2
org.elasticsearch
elasticsearch
5.5.2
内容管理系统,添加TransportClient依赖:
org.elasticsearch.client
transport
这样,内容管理微服务对TransportClient和Elasticsearch(前者依赖后者,版本需要统一)的Jar包都使用的5.5.2版本的了:
这里需要注意,你服务器的版本需要和这里的统一,否则会造成连接失败。
2. 创建TransportClient对象,由Spring容器对其管理。
package liwen.zhao.config;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.InetAddress;
import java.util.List;
@Configuration
@ConfigurationProperties("config.es")
public class ESconfig {
private List nodes;
public List getNodes() {
return nodes;
}
public void setNodes(List nodes) {
this.nodes = nodes;
}
private TransportClient transportClient;
@Bean
public TransportClient iniTransportClient(){
transportClient=new PreBuiltTransportClient(Settings.EMPTY);
//获取配置文件中nodes节点信息中的ip和port
for(String node: nodes){
String ip=node.split(":")[0];
String port=node.split(":")[1];
try {
InetSocketTransportAddress address= new InetSocketTransportAddress(InetAddress.getByName(ip), Integer.parseInt(port));
transportClient.addTransportAddress(address);
} catch (Exception e) {
e.printStackTrace();
}
}
return transportClient;
}
}
创建操作TransportClient的工具类:
package liwen.zhao.utils;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.client.transport.TransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("esUtil")
public class ESUtil {
@Autowired
TransportClient transportClient;
//创建索引
public TransportClient indexIsExists(String name){
transportClient.admin().indices().prepareCreate(name).get().isAcknowledged();
//拿到集群索引管理对象
IndicesAdminClient indicesAdminClient = transportClient.admin().indices();
//判断这个索引是否存在
IndicesExistsResponse indicesExistsResponse = indicesAdminClient.prepareExists(name).get();
if(!indicesExistsResponse.isExists()){
throw new RuntimeException("already exists");
}else{
return transportClient;
}
}
}
配置文件中需要添加:
#Elasticsearch
config.es.nodes=192.168.43.88:9300
1.控制层和业务层代码实现
控制层:
@Controller
@RestController
@RequestMapping("/es")
public class ElasticsearchController {
@Autowired
private ElasticsearchService elasticsearchService;
@RequestMapping("/createIndex")
public SysResult createIndex(String indexName,String type){
return elasticsearchService.createIndexByNameAndType(indexName,type);
}
}
业务逻辑层:
package liwen.zhao.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import liwen.zhao.common.jd.pojo.Article;
import liwen.zhao.common.jd.vo.SysResult;
import liwen.zhao.mappers.ArticleMapper;
import liwen.zhao.utils.ESUtil;
import org.elasticsearch.client.transport.TransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class ElasticsearchServiceImpl implements ElasticsearchService {
@Autowired
ArticleMapper articleMapper;
@Autowired
private ESUtil esUtil;
private ObjectMapper mapper=new ObjectMapper();
@Override
public SysResult createIndexByNameAndType(String indexName,String type) {
try{
TransportClient client = esUtil.indexIsExists(indexName);
//创建索引成功
//将document数据写入到索引中 type
//读取数据库数 0,100
List articles = articleMapper.selectArticleByPage(0, 100);
for(Article a:articles){
//每次拿到一个商品对象
//String aJson = mapper.writeValueAsString(p);
Map articleMap=new HashMap();
articleMap.put("title",a.getTitle());
articleMap.put("content",a.getContent());
articleMap.put("img",a.getImg());
client.prepareIndex(indexName,type,a.getId()+"")
.setSource(articleMap).get();
}
return SysResult.ok();
}catch (Exception e){
e.printStackTrace();
return SysResult.build(500,"索引创建失败!",null);
}
}
}
2.完成商品索引的创建
在浏览器输入:http://localhost/es/createIndex?indexName=jd&type=shop,将创建索引名称为jd,类型为shop的索引。并将数据库的100条数据录入到Elasticsearch。
ps:这个操作直接暴露在外不太安全和正规,应该在后台进行操作并添加认证授权流程。还是那句话,实现京东商城的每个细节不太现实,本次目标主要是为了通过Elasticsearch实现一下搜索功能。
前端代码-数据获取:
前端代码-数据绑定:
-
- {{shop.title}}
- ¥{{shop.price}}
- 已有10人评价
我们看到,前两个商品,和手机密切相关,搜出来了,权重最高,排在了前面。第三个商品,机油里有“机”,次相关。后面两个商品,手表里有“手”,也是次相关。
本案例,通过elasticsearch实现了商品搜索功能。 除建立索引用到了数据库,其它过程都是Elasticsearch实现的。 这样既实现了精准搜索,又减小了数据库访问压力。