编辑solr_home\solr_core\conf下的managed-schema文件
这些是原有的field,不用更改,其中"_text_"的text_general类型,在上一篇博客:Solr搜索引擎学习笔记之Solr服务器搭建 已设置了中文分词器smartcn
id
这些是新添加的field,可根据自己的实体类进行添加
这些是复制域,用于全文检索的字段
org.apache.solr
solr-solrj
6.4.2
private HttpSolrClient solrClient=new HttpSolrClient("http://localhost:8080/solr/solr_core");
solrClient=new HttpSolrClient.Builder("http://localhost:8080/solr/solr_core").build();
solrClient.setConnectionTimeout(500);
solrClient.setSoTimeout(1000);
package com.lmz.entity;
import java.io.Serializable;
import java.sql.Timestamp;
import org.apache.solr.common.SolrInputDocument;
public class Book implements Serializable{
/** serialVersionUID */
private static final long serialVersionUID = 1L;
/** id */
private Long id;
/** 书名 */
private String bookName;
/** 作者 */
private Author author;
/** 状态[0:下架;1:上架] */
private Integer status;
/** 内容 */
private String content;
/** 出版时间 */
private Timestamp publishDate;
通过实体获取全文检索文档,实体属性对应上面配置field
/**
* 获取solr全文检索对象
*
* @param book
*
* @return 全文检索对象
*/
public SolrInputDocument getSolrInputDocument(Book book) {
SolrInputDocument document=new SolrInputDocument();
document.addField("id", book.getId());
document.addField("bookName", book.getBookName());
document.addField("status", book.getStatus());
document.addField("content", book.getContent());
document.addField("publishDate", book.getPublishDate().getTime());
if (book.getAuthor()!=null) {
document.addField("author_id", book.getAuthor().getId());
document.addField("author_name", book.getAuthor().getName());
document.addField("author_nickname", book.getAuthor().getNickname());
}
return document;
}
package com.lmz.entity;
import java.io.Serializable;
/**
* 作者实体
*
*/
public class Author implements Serializable{
/** serialVersionUID */
private static final long serialVersionUID = 1L;
/** id */
private Long id;
/** 名字 */
private String name;
/** 昵称 */
private String nickname;
包括了索引的增删改,修改方法就是添加方法,id相同的数据会覆盖掉,查询方法过于复杂,不在此
package com.lmz.utils;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.lmz.exception.SolrCheckException;
/**
* solr工具类
*
*/
@Component
public class SolrUtils {
@Autowired
private HttpSolrClient solrClient;
public SolrUtils(){
}
添加单个文档对象到检索库
/**
* 添加对象到全文检索
*
* @param document
* @throws IOException
* @throws SolrServerException
* @throws SolrCheckException
*/
public void add(SolrInputDocument document) throws SolrServerException, IOException, SolrCheckException {
UpdateResponse response = solrClient.add(document);
if (response.getStatus() == 0) {
solrClient.commit();
} else {
throw new SolrCheckException("solr add error");
}
}
添加多个文档对象到检索库
/**
* 添加对象到全文检索
*
* @param document
* @throws IOException
* @throws SolrServerException
* @throws SolrCheckException
*/
public void add(Collection docs) throws IOException, SolrServerException, SolrCheckException {
if (docs != null && docs.size() > 0) {
UpdateResponse response = solrClient.add(docs);
if (response.getStatus() == 0) {
solrClient.commit();
} else {
throw new SolrCheckException("solr add error");
}
}
}
上面是配置field的文档添加,若没有配置field,可在实体属性上使用@Field注解就行,也不必获取检索文档对象,便可直接添加
/**
* 添加bean对象到全文检索
* @param object
* @throws IOException
* @throws SolrServerException
* @throws SolrCheckException
*/
public void addByBean(Object object) throws IOException, SolrServerException, SolrCheckException {
UpdateResponse response=solrClient.addBean(object);
if (response.getStatus() == 0) {
solrClient.commit();
} else {
throw new SolrCheckException("solr add error");
}
}
/**
* 添加bean对象到全文检索
*
* @param document
* @throws IOException
* @throws SolrServerException
* @throws SolrCheckException
*/
public void addByBean(Collection
删除检索
/**
* 在全文检索中移除对象
*
* @param id
* @throws SolrServerException
* @throws IOException
* @throws SolrCheckException
*/
public void delete(String id) throws SolrServerException, IOException, SolrCheckException {
UpdateResponse response=solrClient.deleteById(id);
if (response.getStatus()==0) {
solrClient.commit();
} else {
throw new SolrCheckException("solr delete error");
}
}
/**
* 在全文检索中移除对象
*
* @param id
* @throws SolrServerException
* @throws IOException
* @throws SolrCheckException
*/
public void delete(List ids) throws SolrServerException, IOException, SolrCheckException {
UpdateResponse response=solrClient.deleteById(ids);
if (response.getStatus()==0) {
solrClient.commit();
} else{
throw new SolrCheckException("solr delete error");
}
}
/**
* 删除全文检索的所有对象
*
* @throws SolrServerException
* @throws IOException
* @throws SolrCheckException
*/
public void deleteAll() throws SolrServerException, IOException, SolrCheckException {
UpdateResponse response=solrClient.deleteByQuery("*");
if (response.getStatus()==0) {
solrClient.commit();
} else {
throw new SolrCheckException("solr delete all error");
}
}
获取solr的server接口
/**
* 获取solrClient
* @return
*/
public SolrClient getSolrClient() {
return solrClient;
}
package com.lmz.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 时间工具类
*
*/
public class DateUtils {
/**
* 根据当前时间获取id
* @return id
*/
public static Long getIDByDate() {
SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddmmss");
String idStr=sdf.format(new Date());
return new Long(idStr);
}
}
package com.lmz.bean;
import java.io.Serializable;
import java.util.List;
public class SolrSearchBean implements Serializable {
/** SerialVersionUID */
private static final long serialVersionUID = 1L;
/** 关键字列表 */
private List keywordList;
/** 排序类型[0:倒序;1:正序] */
private Integer orderType;
/** 过滤条件:状态[0:下架;1:上架] */
private Integer status;
/** 是否高亮 */
private Boolean ifHL;
/** 当前页数 */
private Integer pageNo;
/** 页面大小 */
private Integer pageSize;
package com.lmz.bean;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* 分页结果类
* @param
*
*/
public class PageResult implements Serializable{
/** serialVersionUID */
private static final long serialVersionUID = 1L;
/** 当前页 */
private Integer pageNo;
/** 每页大小 */
private Integer pageSize;
/** 总数 */
private Long count;
/**总页数*/
private Integer totalPage;
/** list集合数据 */
private List list;
/** map集合数据 */
private Map
package com.lmz.service;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lmz.bean.PageResult;
import com.lmz.bean.SolrSearchBean;
import com.lmz.entity.Author;
import com.lmz.entity.Book;
import com.lmz.exception.SolrCheckException;
import com.lmz.utils.SolrUtils;
/**
* solr服务
*
*/
@Service
public class BookSolrService {
/** solr工具类 */
@Autowired
private SolrUtils solrUtils;
/**
* 删除全部索引
*
* @throws SolrServerException
* @throws IOException
* @throws SolrCheckException
*/
public void delAll() throws SolrServerException, IOException, SolrCheckException {
solrUtils.deleteAll();
}
/**
* 添加索引
*
* @param book
* @throws SolrCheckException
* @throws IOException
* @throws SolrServerException
*/
public void addSolrServer(Book book) throws SolrServerException, IOException, SolrCheckException {
solrUtils.add(book.getSolrInputDocument(book));
}
获取SolrQuery,设置检索条件
/**
* 通过搜索实体获取SolrQuery
*
* @param bean
* 搜索实体
* @return SolrQuery
*/
private SolrQuery getSolrQuery(SolrSearchBean bean) {
SolrQuery query = new SolrQuery();
StringBuffer sb_q = new StringBuffer();
if (bean.getKeywordList() == null || bean.getKeywordList().size() == 0) {
// 没有关键字则全查
sb_q.append("*");
} else {
for (int i = 0; i < bean.getKeywordList().size(); i++) {
if (i == 0) {
sb_q.append(bean.getKeywordList().get(i));
} else {
sb_q.append(" AND ").append(bean.getKeywordList().get(i));
}
}
}
// 若是全查,取消高亮
if ("*".equals(sb_q.toString())) {
bean.setIfHL(false);
}
// 设置检索关键字,从"_text_"域中检索,也就是复制域中设置了该域的域
query.set("q", "_text_:" + sb_q.toString());
StringBuffer sb_fq = new StringBuffer();
// 过滤状态
if (bean.getStatus() != null && bean.getStatus() >= 0) {
addStr(sb_fq);
sb_fq.append("status:" + bean.getStatus());
}
// 设置过滤条件
if (sb_fq.length() > 0) {
query.set("fq", sb_fq.toString());
}
//指定查询输出结构格式
query.set("wt", "json");
// 设置分页
// 开始页,solr第一页从0开始
query.setStart(bean.getPageNo() - 1);
// 每页大小
query.setRows(bean.getPageSize());
// 排序
if (bean.getOrderType() != null && bean.getOrderType() >= 0) {
if (bean.getOrderType() == 0) {
query.addSort("publishDate", SolrQuery.ORDER.desc);
} else {
query.addSort("publishDate", SolrQuery.ORDER.asc);
}
}
// 设置高亮
if (bean.getIfHL()) {
// 开启高亮
query.setHighlight(true);
// 添加高亮字段
query.addHighlightField("bookName");
query.addHighlightField("content");
query.addHighlightField("author_name");
query.addHighlightField("author_nickname");
// 高亮的头部分
query.setHighlightSimplePre("");
// 高亮的尾部分
query.setHighlightSimplePost("");
}
return query;
}
搜索
/**
* 搜索
*
* @param bean
* 搜索实体
* @return 搜索结果集
* @throws SolrCheckException
*/
public PageResult search(SolrSearchBean bean) throws SolrCheckException {
// 获取SolrQuery
SolrQuery query = getSolrQuery(bean);
// 搜索响应
QueryResponse response = null;
// 结果分页
PageResult page = new PageResult();
// 设置结果分页
page.setPageNo(bean.getPageNo());
page.setPageSize(bean.getPageSize());
page.setCount(0L);
page.setTotalPage(0);
try {
// 执行搜索
response = solrUtils.getSolrClient().query(query);
// 获取搜索结果文档
SolrDocumentList documentList = response.getResults();
// 获取所有高亮的字段
Map>> highlightMap = response.getHighlighting();
// 设置搜索总数
page.setCount(documentList.getNumFound());
// 设置总页数
page.setTotalPage((int) (page.getCount() % page.getPageSize() == 0 ? page.getCount() / page.getPageSize()
: page.getCount() / page.getPageSize() + 1));
// 图书集合
List books = new ArrayList();
Book book = null;
Author author = null;
// 从结果文档中获取数据,并封装实体
for (SolrDocument solrDocument : documentList) {
book = new Book();
book.setId(new Long(solrDocument.getFieldValue("id").toString()));
book.setBookName(solrDocument.getFieldValue("bookName").toString());
book.setContent(solrDocument.getFieldValue("content").toString());
book.setStatus(new Integer(solrDocument.getFieldValue("status").toString()));
book.setPublishDate(
new Timestamp(Long.parseLong(solrDocument.getFieldValue("publishDate").toString())));
author = new Author();
author.setId(new Long(solrDocument.getFirstValue("author_id").toString()));
author.setName(solrDocument.getFieldValue("author_name").toString());
author.setNickname(solrDocument.getFirstValue("author_nickname").toString());
// 获取并设置高亮字段
if (bean.getIfHL()) {
String id = solrDocument.getFieldValue("id").toString();
/* 高亮集合里不是去不内容,仅仅只是含有高亮的部分,
* 如果字段数据比较大,那么搜索出来的数据就会截掉不属于高亮的部分,
* 因此这也是使用集合来封装数据的原因
*/
List bookNameList = highlightMap.get(id).get("bookName");
List contentList = highlightMap.get(id).get("content");
List authorNameList = highlightMap.get(id).get("author_name");
List authorNicknameList = highlightMap.get(id).get("author_nickname");
if (bookNameList != null && bookNameList.size() > 0) {
book.setBookName(bookNameList.get(0));
}
if (contentList != null && contentList.size() > 0) {
book.setContent(contentList.get(0));
}
if (authorNameList != null && authorNameList.size() > 0) {
author.setName(authorNameList.get(0));
}
if (authorNicknameList != null && authorNicknameList.size() > 0) {
author.setNickname(authorNicknameList.get(0));
}
}
book.setAuthor(author);
books.add(book);
}
page.setList(books);
} catch (SolrServerException | IOException e) {
throw new SolrCheckException("solr search error");
}
return page;
}
/**
* 在字符串末尾追加" and "
*
* @param sb_fq
*/
private void addStr(StringBuffer sb_fq) {
if (sb_fq.length() > 0) {
sb_fq.append(" and ");
}
}
package com.lmz.controller;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.apache.solr.client.solrj.SolrServerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.lmz.bean.PageResult;
import com.lmz.bean.SolrSearchBean;
import com.lmz.entity.Book;
import com.lmz.exception.SolrCheckException;
import com.lmz.service.BookSolrService;
import com.lmz.utils.DateUtils;
@Controller
public class SolrTestController {
@Autowired
private BookSolrService bookSolrService;
/**
* 添加索引
* @param model
* @param book book对象,包含author对象
* @return
*/
@RequestMapping("/add")
public String add(Model model,Book book) {
String msg="添加成功";
Long id=DateUtils.getIDByDate();
book.setId(id);
book.getAuthor().setId(id);
book.setPublishDate(new Timestamp(new Date().getTime()));
try {
bookSolrService.addSolrServer(book);
} catch (SolrServerException | IOException | SolrCheckException e) {
msg="添加失败";
}
model.addAttribute("msg", msg);
return "index";
}
/**
* 全文检索
* @param model
* @param bean solr搜索对象
* @return
*/
@RequestMapping("/search")
public String search(Model model,SolrSearchBean bean) {
//去除集合中空数据
if (bean.getKeywordList()!=null) {
for (int i = 0; i < bean.getKeywordList().size();) {
if (StringUtils.isBlank(bean.getKeywordList().get(i))) {
bean.getKeywordList().remove(i);
if (i >= bean.getKeywordList().size()) {
break;
}
} else {
i++;
}
}
}
//设置分页
bean.setPageNo(1);
bean.setPageSize(10);
//分页结果
PageResult page=null;
//搜索
try {
page = bookSolrService.search(bean);
} catch (SolrCheckException e) {
//solr异常,组装空结果
page=new PageResult();
page.setCount(0l);
page.setTotalPage(0);
page.setPageNo(0);
page.setPageSize(bean.getPageSize());
page.setList(new ArrayList());
}
model.addAttribute("page", page);
return "search";
}
/**
* 删除全部索引
* @return
*/
@RequestMapping("/del")
@ResponseBody
public String del() {
try {
bookSolrService.delAll();
} catch (SolrServerException | IOException | SolrCheckException e) {
return "删除失败";
}
return "删除成功";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
添加索引
搜索
删除全部索引
${msg}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
Insert title here
序号
id
bookName
status
content
publishDate
author_id
author_name
author_nickname
${i.index}
${l.id}
${l.bookName}
${l.status}
${l.content}
${l.publishDate}
${l.author.id}
${l.author.name}
${l.author.nickname}
共${page.count}条记录 第${page.pageNo}页 共${page.totalPage}页
ok,整个实例已写完,下面来测试结果如何吧
测试这里就进行添加和检索,删除因为就写了一个全删测试,就不进行了,修改的话就如同添加。
点击添加后,到solr管理页面,查看是否添加成功
这是检索全部数据,如果出现刚才新添加的数据就说明添加成功,如下:
这是检索页面,如果没填关键字就会检索全部数据,现在就填写关键字:我的游戏,结果如下:
ok,其它的搜索,就由你们完成了,现在整个实例就完成了......