一:创建taotao core
1、 在example目录下创建taotao-solr文件夹;
2、 将./solr下的solr.xml拷贝到taotao-solr目录下;
3、 在taotao-solr下创建taotao目录,并且在taotao目录下创建conf和data目录;
4、 将example\solr\collection1\core.properties文件拷贝到example\taotao-solr\taotao下,并且修改name=taotao;
5、 将example\solr\collection1\conf下的schema.xml、solrconfig.xml拷贝到example\taotao-solr\taotao\conf下;
6、 修改schema.xml文件,使其配置最小化:
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="example" version="1.5">
<field name="_version_" type="long" indexed="true" stored="true"/>
<field name="_root_" type="string" indexed="true" stored="false"/>
<field name="id" type="long" indexed="true" stored="true" required="true" multiValued="false" />
<field name="title" type="text_ik" indexed="true" stored="true"/>
<field name="sellPoint" type="string" indexed="false" stored="true"/>
<field name="price" type="long" indexed="true" stored="true"/>
<field name="image" type="string" indexed="false" stored="true"/>
<field name="cid" type="long" indexed="true" stored="true"/>
<field name="status" type="int" indexed="true" stored="false"/>
<uniqueKey>id</uniqueKey>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
<solrQueryParser defaultOperator="AND"/>
</schema>
7、 修改solrconfig.xml文件,修改一些配置,大部分配置先保持默认:
a) 将所有的<lib>标签注释掉;
b) 搜索<str name="df">text</str>替换成<str name="df">title</str>
c) 将<searchComponent name="elevator" class="solr.QueryElevationComponent" >注释掉(这个的功能类似百度的竞价排名):
8、 启动solr:
java -Dsolr.solr.home=taotao-solr -jar start.jar
二、集成IK分析器
1、 将IKAnalyzer-2012-4x.jar拷贝到example\solr-webapp\webapp\WEB-INF\lib下;
2、 在schema.xml文件中添加fieldType(上面已写好,这里忽略):
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
三、配置nginx 通过域名访问 solr
server {
listen 80;
server_name solr.taotao.com;
#charset koi8-r;
#access_log logs/host.access.log main;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
location / {
proxy_pass http://127.0.0.1:8983;
proxy_connect_timeout 600;
proxy_read_timeout 600;
}
}
四、添加host
五、 将商品数据导入到solr
1、商品
package cn.itcast.solrj.pojo;
import org.apache.solr.client.solrj.beans.Field;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* 商品
*
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Item {
@Field("id")
private Long id;
@Field("title")
private String title;
@Field("sellPoint")
private String sellPoint;
@Field("price")
private Long price;
@Field("image")
private String image;
@Field("cid")
private Long cid;
@Field("status")
private Integer status;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSellPoint() {
return sellPoint;
}
public void setSellPoint(String sellPoint) {
this.sellPoint = sellPoint;
}
public Long getPrice() {
return price;
}
public void setPrice(Long price) {
this.price = price;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Long getCid() {
return cid;
}
public void setCid(Long cid) {
this.cid = cid;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
@Override
public String toString() {
return "Item [id=" + id + ", title=" + title + ", sellPoint=" + sellPoint + ", price=" + price
+ ", image=" + image + ", cid=" + cid + ", status=" + status + "]";
}
}
2、EasyUIResult
package cn.itcast.solrj.pojo;
import java.util.List;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class EasyUIResult {
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
private Integer total;
private List<?> rows;
public EasyUIResult() {
}
public EasyUIResult(Integer total, List<?> rows) {
this.total = total;
this.rows = rows;
}
public EasyUIResult(Long total, List<?> rows) {
this.total = total.intValue();
this.rows = rows;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public List<?> getRows() {
return rows;
}
public void setRows(List<?> rows) {
this.rows = rows;
}
/**
* Object是集合转化
*
* @param jsonData json数据
* @param clazz 集合中的类型
* @return
*/
public static EasyUIResult formatToList(String jsonData, Class<?> clazz) {
try {
JsonNode jsonNode = MAPPER.readTree(jsonData);
JsonNode data = jsonNode.get("rows");
List<?> list = null;
if (data.isArray() && data.size() > 0) {
list = MAPPER.readValue(data.traverse(),
MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
}
return new EasyUIResult(jsonNode.get("total").intValue(), list);
} catch (Exception e) {
return null;
}
}
}
3、测试导入
package cn.itcast.solrj.service;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.junit.Test;
import cn.itcast.solrj.pojo.EasyUIResult;
import cn.itcast.solrj.pojo.Item;
public class ItemDataImport {
@Test
public void start() throws Exception {
// 1、从数据库中查询商品数据
String url = "http://manage.taotao.com/rest/item?page={page}&rows=100";
// 定义httpsolrserver
// http://solr.taotao.com/#/taotao -- 网页地址
String solrUrl = "http://solr.taotao.com/taotao";
HttpSolrServer httpSolrServer = new HttpSolrServer(solrUrl); //定义solr的server
httpSolrServer.setParser(new XMLResponseParser()); // 设置响应解析器
httpSolrServer.setMaxRetries(1); // 设置重试次数,推荐设置为1
httpSolrServer.setConnectionTimeout(500); // 建立连接的最长时间
// 分页获取数据
Integer page = 1;
Integer pageSize = 0;
do {
String jsonData = doGet(StringUtils.replace(url, "{page}", String.valueOf(page)));
EasyUIResult easyUIResult = EasyUIResult.formatToList(jsonData, Item.class);
List<Item> rows = (List<Item>) easyUIResult.getRows();
pageSize = rows.size();
// 2、将商品数据写入到solr
httpSolrServer.addBeans(rows);
httpSolrServer.commit();
page++;
} while (pageSize == 100);
}
private String doGet(String url) {
try {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建http GET请求
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = null;
try {
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
return EntityUtils.toString(response.getEntity(), "UTF-8");
}
} finally {
if (response != null) {
response.close();
}
httpclient.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
六、
Solr
和
Spring
的整合applicationContext-solr.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg index="0" value="${solr.url}"/>
<property name="parser">
<!-- 设置相应解析器 -->
<bean class="org.apache.solr.client.solrj.impl.XMLResponseParser"/>
</property>
<!-- 重试次数 -->
<property name="maxRetries" value="${solr.maxRetries}"/>
<!-- 建立连接的最长时间 -->
<property name="connectionTimeout" value="${solr.connectionTimeout}"/>
</bean>
</beans>
solr.properties:
solr.url=http://solr.taotao.com/taotao
solr.maxRetries=1
solr.connectionTimeout=500
七、实现搜索
PageInfo:
package com.taotao.search.bean;
import java.util.List;
public class PageInfo<T> {
private Long total;
private List<T> rows;
public PageInfo() {
}
public PageInfo(Long total, List<T> rows) {
this.total = total;
this.rows = rows;
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
}
Item.java添加一个方法
public String[] getImages(){
return this.getImage()==null?null:StringUtils.split(this.getImage(), ',');
}
ItemSearchService:
package com.taotao.search.service;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.taotao.search.bean.Item;
import com.taotao.search.bean.PageInfo;
@Service
public class ItemSearchService {
public static final Integer ROWS = 28;
@Autowired
private HttpSolrServer httpSolrServer;
public PageInfo<Item> search(String keyword, Integer page) throws Exception {
SolrQuery solrQuery = new SolrQuery(); // 构造搜索条件
solrQuery.setQuery("title:" + keyword + " AND status:1"); // 搜索关键词
// 设置分页 start=0就是从0开始,,rows=5当前返回5条记录,第二页就是变化start这个值为5就可以了。
solrQuery.setStart((Math.max(page, 1) - 1) * ROWS);
solrQuery.setRows(ROWS);
// 是否需要高亮
boolean isHighlighting = !StringUtils.equals("*", keyword) && StringUtils.isNotEmpty(keyword);
if (isHighlighting) {
// 设置高亮
solrQuery.setHighlight(true); // 开启高亮组件
solrQuery.addHighlightField("title");// 高亮字段
solrQuery.setHighlightSimplePre("<em>");// 标记,高亮关键字前缀
solrQuery.setHighlightSimplePost("</em>");// 后缀
}
// 执行查询
QueryResponse queryResponse = this.httpSolrServer.query(solrQuery);
List<Item> items = queryResponse.getBeans(Item.class);
if (isHighlighting) {
// 将高亮的标题数据写回到数据对象中
Map<String, Map<String, List<String>>> map = queryResponse.getHighlighting();
for (Map.Entry<String, Map<String, List<String>>> highlighting : map.entrySet()) {
for (Item item : items) {
if (!highlighting.getKey().equals(item.getId().toString())) {
continue;
}
item.setTitle(StringUtils.join(highlighting.getValue().get("title"), ""));
break;
}
}
}
return new PageInfo<Item>(queryResponse.getResults().getNumFound(), items);
}
}
ItemSearchController:
package com.taotao.search.controller;
import java.io.UnsupportedEncodingException;
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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.taotao.search.bean.Item;
import com.taotao.search.bean.PageInfo;
import com.taotao.search.service.ItemSearchService;
@Controller
public class ItemSearchController {
@Autowired
private ItemSearchService itemSearchService;
@RequestMapping(value="search",method = RequestMethod.GET)
public ModelAndView search(@RequestParam("keyword")String keyword,
@RequestParam(value="page",defaultValue="1")Integer page){
try {
//解决get请求乱码问题
keyword=new String(keyword.getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
ModelAndView mv=new ModelAndView("search");
mv.addObject("query", keyword);
mv.addObject("page", page);
try {
PageInfo<Item> pageInfo=this.itemSearchService.search(keyword,page);
mv.addObject("itemList", pageInfo.getRows());
mv.addObject("pages", (pageInfo.getTotal()+ItemSearchService.ROWS-1)/ItemSearchService.ROWS);
} catch (Exception e) {
e.printStackTrace();
}
return mv;
}
}