solr控制台相信比较容易,简单摸索就可以学会使用了,对于后端开发人员来说还是直接用程序代码操作直观些,因此这次特别拿出了我的学习小例子分享给大家,demo使用springboot开发,图片服务器使用nodejs(也可以使用nginx或者其他方式)
1 程序依赖pom和配置文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.debug</groupId>
<artifactId>FirstSolr</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>FirstSolr</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- tomcat 的支持.-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
springboot的配置文件如下:
server.port=8090
#server.context-path=/shiro/
#server.servlet.context-path=/axmobile/
#DataBase DataSources
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/shiro?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username = root
spring.datasource.password = 123456
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.max-active=20
spring.datasource.max-idle=8
spring.datasource.min-idle=8
spring.datasource.initial-size=10
#mybatis.typeAliasesPackage=com.debug
#mybatis.config-location=classpath:mybatis-config.xml
#mybatis.mapperLocations=classpath:/com/debug/mapper/**/*.xml
spring.data.solr.host=http://127.0.0.1:8089/solr
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
logging.level.com.debug=debug
暂时只需要指定下solr的主机地址即可,如有安全性方面的要求运行有solr环境的服务器需要做诸如防火墙、端口等的访问限制
2 solr数据的初始化
这里初始化几条汽车相关的信息到solr,让solr进行存储和索引
package com.debug.entity;
import org.apache.solr.client.solrj.beans.Field;
public class Goods {
@Field("id")
private String id;
@Field("goods_name")
private String name;
@Field("goods_price")
private double price;
@Field("goods_skuProps")
private String[] skuProps;
@Field("goods_imageUrl")
private String imageUrl;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String[] getSkuProps() {
return skuProps;
}
public void setSkuProps(String[] skuProps) {
this.skuProps = skuProps;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
}
上面的实体类和平时使用的差异不大,我们使用solr的注解@Filed让实体的属性和solr的索引名称建立映射关系,这里为了研究和学习方便直接使用了自带的几条索引,如果不够也可以自行到schema.xml里面新增索引
public void initGoodsSolor() {
List<Goods> ls0 = new ArrayList<Goods>();
Goods g1 = new Goods();
String skuProp[] = { "黑色", "白色" };
g1.setId("goods_" + UUID.randomUUID().toString());
g1.setName("新捷达");
g1.setPrice(80000);
g1.setSkuProps(skuProp);
g1.setImageUrl("/images/xjd.jpg");
ls0.add(g1);
Goods g2 = new Goods();
// String skuProp[]= {"黑色","白色"};
g2.setId("goods_" + UUID.randomUUID().toString());
g2.setName("奥迪A6");
g2.setPrice(250000);
g2.setSkuProps(skuProp);
g2.setImageUrl("/images/ad.jpg");
ls0.add(g2);
Goods g3 = new Goods();
// String skuProp[]= {"黑色","白色"};
g3.setId("goods_" + UUID.randomUUID().toString());
g3.setName("宝骏");
g3.setPrice(250000);
g3.setSkuProps(skuProp);
g3.setImageUrl("/images/bj.jpg");
ls0.add(g3);
Goods g4 = new Goods();
// String skuProp[]= {"黑色","白色"};
g4.setId("goods_" + UUID.randomUUID().toString());
g4.setName("宝来");
g4.setPrice(110000);
g4.setSkuProps(skuProp);
g4.setImageUrl("/images/bl.jpg");
ls0.add(g4);
Goods g5 = new Goods();
// String skuProp[]= {"黑色","白色"};
g5.setId("goods_" + UUID.randomUUID().toString());
g5.setName("宝马");
g5.setPrice(500000);
g5.setSkuProps(skuProp);
g5.setImageUrl("/images/bm.jpg");
ls0.add(g5);
Goods g6 = new Goods();
// String skuProp[]= {"黑色","白色"};
g6.setId("goods_" + UUID.randomUUID().toString());
g6.setName("东风风神");
g6.setPrice(75000);
g6.setSkuProps(skuProp);
g6.setImageUrl("/images/dffs.jpg");
ls0.add(g6);
try {
solrClient.addBeans(ls0);
solrClient.commit();
// solrClient.addBeans(ls);
// solrClient.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
solrClient从外部注入即可,后面会把这个service贴出来,大家稍安勿躁
3 实现搜索功能并把搜索关键字标红
public List<Goods> queryGoods(String name, String end) {
List<Goods> result = new ArrayList<Goods>();
SolrQuery query = new SolrQuery();
// 下面设置solr查询参数
// query.set("q", "*:*");// 参数q 查询所有
query.set("q", "goods_name:" + name);// 相关查询,比如某条数据某个字段含有周、星、驰三个字 将会查询出来 ,这个作用适用于联想查询
// 过滤条件
// query.set("fq", "price:[600 TO 1000]");
// 参数sort,设置返回结果的排序规则
query.setSort("goods_price", SolrQuery.ORDER.asc);
// 设置分页参数
query.setStart(0);
query.setRows(Integer.parseInt(end));// 每一页多少值
// 参数hl,设置高亮
query.setHighlight(true);
// 设置高亮的字段
query.addHighlightField("goods_name");
// 设置高亮的样式
query.setHighlightSimplePre("<font color='red'>");
query.setHighlightSimplePost("</font>");
// query.setParam("hl.fl", "name");
// 获取查询结果
QueryResponse response = null;
try {
response = solrClient.query(query);
} catch (SolrServerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 两种结果获取:得到文档集合或者实体对象
// 查询得到文档的集合
SolrDocumentList solrDocumentList = response.getResults();
// System.out.println("通过文档集合获取查询的结果");
// System.out.println("查询结果的总数量:" + solrDocumentList.getNumFound());
List<Goods> goodsList = response.getBeans(Goods.class);
Map<String, Map<String, List<String>>> maplist = response.getHighlighting();
// 返回高亮之后的结果..
for (Goods g : goodsList) {
String id = g.getId();
double price = g.getPrice();
String imageUrl = g.getImageUrl();
Map<String, List<String>> fieldMap = maplist.get(id);
List<String> stringlist = fieldMap.get("goods_name");
Goods g1 = new Goods();
g1.setName(stringlist.get(0));
g1.setPrice(new Double(price).doubleValue());
g1.setImageUrl(imageUrl);
result.add(g1);
}
return result;
}
只要获取到solr返回给我们的结果,下面的工作就很简单了,无外乎就是数据展示相关了
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询结果</title>
<style type="text/css">
ul{
list-style:none;
}
ul li{
text-decoration: none;float:left;margin-left:20px;
}
.top{
margin-top:20px;
}
.goodsImg{
width:200px;
height:250px;
}
</style>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<c:forEach var="item" items="${result}">
<div class="col-md-3 top">
<div><img class="goodsImg" src="http://localhost:9091${item.imageUrl}"/></div>
<div>${item.name}</div>
</div>
</c:forEach>
</div>
</div>
</div>
</body>
</html>
运行效果如下
图片选的不是很好,界面难看了点,大家凑合看看就行
下面把controller和service的完整代码贴出来给大家参考
package com.debug.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.solr.client.solrj.SolrClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.debug.service.SolrService;
@Controller
@RequestMapping("/solrHandler")
public class SolrController {
@Resource
private SolrService solrService;
@Autowired
private SolrClient solrClient;
@RequestMapping("/initGoodsSolor")
@ResponseBody
public String initGoodsSolor() {
solrService.initGoodsSolor();
return "操作成功";
}
@RequestMapping("/initSolr")
@ResponseBody
public String initSolr() {
solrService.initSolor();
return "操作成功";
}
@RequestMapping("/query")
public String query(HttpServletRequest request,String name) {
request.setAttribute("result", solrService.query(name));
return "query";
}
@RequestMapping("/queryGoods")
public String queryGoods(HttpServletRequest request,String name,String end) {
request.setAttribute("result", solrService.queryGoods(name,end));
return "queryGoods";
}
/**
* 删除所有的索引
* @return
*/
@RequestMapping("deleteAll")
@ResponseBody
public String deleteAll(){
try {
solrClient.deleteByQuery("collection1","*:*");
solrClient.commit("collection1");
return "success";
} catch (Exception e) {
e.printStackTrace();
}
return "error";
}
}
package com.debug.service.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.debug.entity.Goods;
import com.debug.service.SolrService;
@Service
public class SolrServiceImpl implements SolrService {
@Autowired
private SolrClient solrClient;
public void initSolor() {
List<SolrInputDocument> ls0 = new ArrayList<SolrInputDocument>();
for (int i = 1; i <= 10; i++) {
SolrInputDocument doc = new SolrInputDocument();
doc.setField("id", "goods_" + i);
doc.setField("name", "手机" + i);
doc.setField("price", new Random().nextInt(1000));
doc.setField("description", "产品介绍" + i);
ls0.add(doc);
}
List<SolrInputDocument> ls = new ArrayList<SolrInputDocument>();
for (int i = 1; i <= 10; i++) {
SolrInputDocument doc = new SolrInputDocument();
doc.setField("id", "goods_" + 10 + i);
doc.setField("name", "笔记本电脑" + i);
doc.setField("price", new Random().nextInt(1000));
doc.setField("description", "产品介绍" + i);
ls.add(doc);
}
try {
solrClient.add(ls0);
solrClient.add(ls);
solrClient.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// solrClient.close();
}
public List<String> query(String name) {
List<String> result = new ArrayList<String>();
SolrQuery query = new SolrQuery();
// 下面设置solr查询参数
// query.set("q", "*:*");// 参数q 查询所有
query.set("q", "name:" + name);// 相关查询,比如某条数据某个字段含有周、星、驰三个字 将会查询出来 ,这个作用适用于联想查询
// 过滤条件
query.set("fq", "price:[600 TO 1000]");
// 参数sort,设置返回结果的排序规则
query.setSort("id", SolrQuery.ORDER.asc);
// 设置分页参数
query.setStart(0);
query.setRows(10);// 每一页多少值
// 参数hl,设置高亮
query.setHighlight(true);
// 设置高亮的字段
query.addHighlightField("name");
// 设置高亮的样式
query.setHighlightSimplePre("<font color='red'>");
query.setHighlightSimplePost("</font>");
// query.setParam("hl.fl", "name");
// 获取查询结果
QueryResponse response = null;
try {
response = solrClient.query(query);
} catch (SolrServerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 两种结果获取:得到文档集合或者实体对象
// 查询得到文档的集合
// SolrDocumentList solrDocumentList = response.getResults();
// System.out.println("通过文档集合获取查询的结果");
// System.out.println("查询结果的总数量:" + solrDocumentList.getNumFound());
SolrDocumentList documentList = response.getResults();
Map<String, Map<String, List<String>>> maplist = response.getHighlighting();
// 返回高亮之后的结果..
for (SolrDocument solrDocument : documentList) {
Object id = solrDocument.get("id");
Map<String, List<String>> fieldMap = maplist.get(id);
List<String> stringlist = fieldMap.get("name");
result.add(stringlist.get(0));
// System.out.println(stringlist);
}
return result;
}
public void initGoodsSolor() {
List<Goods> ls0 = new ArrayList<Goods>();
Goods g1 = new Goods();
String skuProp[] = { "黑色", "白色" };
g1.setId("goods_" + UUID.randomUUID().toString());
g1.setName("新捷达");
g1.setPrice(80000);
g1.setSkuProps(skuProp);
g1.setImageUrl("/images/xjd.jpg");
ls0.add(g1);
Goods g2 = new Goods();
// String skuProp[]= {"黑色","白色"};
g2.setId("goods_" + UUID.randomUUID().toString());
g2.setName("奥迪A6");
g2.setPrice(250000);
g2.setSkuProps(skuProp);
g2.setImageUrl("/images/ad.jpg");
ls0.add(g2);
Goods g3 = new Goods();
// String skuProp[]= {"黑色","白色"};
g3.setId("goods_" + UUID.randomUUID().toString());
g3.setName("宝骏");
g3.setPrice(250000);
g3.setSkuProps(skuProp);
g3.setImageUrl("/images/bj.jpg");
ls0.add(g3);
Goods g4 = new Goods();
// String skuProp[]= {"黑色","白色"};
g4.setId("goods_" + UUID.randomUUID().toString());
g4.setName("宝来");
g4.setPrice(110000);
g4.setSkuProps(skuProp);
g4.setImageUrl("/images/bl.jpg");
ls0.add(g4);
Goods g5 = new Goods();
// String skuProp[]= {"黑色","白色"};
g5.setId("goods_" + UUID.randomUUID().toString());
g5.setName("宝马");
g5.setPrice(500000);
g5.setSkuProps(skuProp);
g5.setImageUrl("/images/bm.jpg");
ls0.add(g5);
Goods g6 = new Goods();
// String skuProp[]= {"黑色","白色"};
g6.setId("goods_" + UUID.randomUUID().toString());
g6.setName("东风风神");
g6.setPrice(75000);
g6.setSkuProps(skuProp);
g6.setImageUrl("/images/dffs.jpg");
ls0.add(g6);
try {
solrClient.addBeans(ls0);
solrClient.commit();
// solrClient.addBeans(ls);
// solrClient.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public List<Goods> queryGoods(String name, String end) {
List<Goods> result = new ArrayList<Goods>();
SolrQuery query = new SolrQuery();
// 下面设置solr查询参数
// query.set("q", "*:*");// 参数q 查询所有
query.set("q", "goods_name:" + name);// 相关查询,比如某条数据某个字段含有周、星、驰三个字 将会查询出来 ,这个作用适用于联想查询
// 过滤条件
// query.set("fq", "price:[600 TO 1000]");
// 参数sort,设置返回结果的排序规则
query.setSort("goods_price", SolrQuery.ORDER.asc);
// 设置分页参数
query.setStart(0);
query.setRows(Integer.parseInt(end));// 每一页多少值
// 参数hl,设置高亮
query.setHighlight(true);
// 设置高亮的字段
query.addHighlightField("goods_name");
// 设置高亮的样式
query.setHighlightSimplePre("<font color='red'>");
query.setHighlightSimplePost("</font>");
// query.setParam("hl.fl", "name");
// 获取查询结果
QueryResponse response = null;
try {
response = solrClient.query(query);
} catch (SolrServerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 两种结果获取:得到文档集合或者实体对象
// 查询得到文档的集合
SolrDocumentList solrDocumentList = response.getResults();
// System.out.println("通过文档集合获取查询的结果");
// System.out.println("查询结果的总数量:" + solrDocumentList.getNumFound());
List<Goods> goodsList = response.getBeans(Goods.class);
Map<String, Map<String, List<String>>> maplist = response.getHighlighting();
// 返回高亮之后的结果..
for (Goods g : goodsList) {
String id = g.getId();
double price = g.getPrice();
String imageUrl = g.getImageUrl();
Map<String, List<String>> fieldMap = maplist.get(id);
List<String> stringlist = fieldMap.get("goods_name");
Goods g1 = new Goods();
g1.setName(stringlist.get(0));
g1.setPrice(new Double(price).doubleValue());
g1.setImageUrl(imageUrl);
result.add(g1);
}
return result;
}
}
使用到的索引如下:
<field name="goods_name" type="text_general" indexed="true" stored="true"/>
<field name="goods_price" type="float" indexed="true" stored="true"/>
<field name="goods_skuProps" type="text_general" indexed="true" stored="true" multiValued="true"/>
<field name="goods_imageUrl" type="text_general" indexed="true" stored="true" multiValued="false"/>
是不是很简单呢,现在除了solr外我们还可以选择Elasticsearch作为搜索引擎,可参考下面这个学习