solr

来源:互联网 发布:c语言整人小程序 编辑:程序博客网 时间:2024/06/06 20:52
什么是solr
Solr Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene全文搜索服务Solr可以独立运行在JettyTomcat等这些Servlet容器中。
使用Solr进行创建索引和搜索索引的实现方法很简单,如下:
创建索引:客户端(可以是浏览器可以是Java程序)用POST方法向Solr服务器发送一个描述Field及其内容的XML文档,Solr服务器根据xml文档添加、删除、更新索引 。
搜索索引:客户端(可以是浏览器可以是Java程序)用GET方法向Solr服务器发送请求,然后对Solr服务器返回Xmljson等格式的查询结果进行解析。Solr不提供构建页面UI的功能。Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。
Solr是一个可以独立运行的搜索服务器,使用solr进行全文检索服务的话,只需要通过http请求访问该服务器即可。
SolrLucene的区别
Lucene是一个开放源代码的全文检索引擎工具包,它不是一个完整的全文检索应用。Lucene仅提供了完整的查询引擎和索引引擎,目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者以Lucene为基础构建全文检索应用。
 Solr的目标是打造一款企业级的搜索引擎系统,它是基于Lucene一个搜索引擎服务,可以独立运行,通过Solr可以非常快速的构建企业的搜索引擎,通过Solr也可以高效的完成站内搜索功能。

1. 什么是solr:
solr是apache公司出品的一个全文检索引擎系统.
solr和lucene区别:
lucene是一个工具包, 放入tomcat不能独立运行,
solr是一个全文检索系统,放入tomcat下可以独立运行,solr底层使用luecene来开发实现的.
2. solr作用:
我们可以不用写大量的对索引和文档的增删改查的代码, 将solr部署到tomcat后就可以独立运行,
solr对外通过htttp的形式提供索引和文档的增删改查服务.

solr部署:
a) 将solr的war包放入tomcat的webapps目录下.
b) 运行tomcat目的是解压war包, 等解压后,关掉黑窗口,然后将webapps下的war删除
c) 将solr/example下的solr目录整个拷贝到硬盘根目录,因为这个是solrHome
要求路径中不能有中文和空格
d) 将solrHome的路径复制到tomcat下webapps/solr/WEB-INF/web.xml中进行配置
e) 将solr/example/lib/ext下的所有log的jar包拷贝到tomcat下solr项目中的lib包中
f) 添加log4j.properties
solr解压包下solr-4.10.3\example\resources\log4j.properties文件进行复制
粘贴到TomcatwebappssolrWEB-INF\classes目录下这里没有classes文 件夹创建一个即可
g) 重新运行tomcat


solrHome:就是solr的家, 一个solr服务器只能有一个solrHome, solrHome中包含多个solrCore,
一个solrCore就是一个solr实例, 一个实例可以对外单独提供索引和文档的增删改查服务, 实例
和实例之间是互相隔离的.

注意: solr中域要先定义后使用,如果没有定义就使用会报错.
ERROR: [doc=002] unknown field 'xxxxxx'

solr每次增加的时候必须有id域, id为主键域没有会报错
Document is missing mandatory uniqueKey field: id"

solr中没有专门的修改方法, 首先根据id去索引库和文档库中去查找, 如果找到了就删除原来的,
将新的添加进去, 如果没有找到, 就直接将新的添加进去



利用浏览器访问界面删除索引和文档:
根据id删除
<delete>
<id>004</id>
</delete>
<commit/>

删除所有
<delete>
<query>*:*</query>
</delete>
<commit/>

 solr基本使用
1. schema.xml
schema.xml文件在SolrCoreconf目录下,在此配置文件中定义了域以及域的类型等一些配置。在solr中域必须先定义后使用。
1.1. field
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
Name:域的名称
Type:域的类型
Indexed:是否索引
Stored:是否存储
Required:是否必须
multiValued:是否是多值,存储多个值时设置为truesolr允许一个Field存储多个值,比如存储一个用户的好友id(多个),商品的图片(多个,大图和小图)
1.2. dynamicField(动态域)
<dynamicField name="*_s"  type="string"  indexed="true"  stored="true" />
Name:动态域的名称,是一个表达式,*匹配任意字符,只要域的名称和表达式的规则能够匹配就可以使用。 
例如:搜索时查询条件[product_i:钻石]就可以匹配这个动态域,可以直接使用,不用单独再定义一个product_i域。
1.3. uniqueKey
<uniqueKey>id</uniqueKey>
相当于主键,每个文档中必须有一个id域。
1.4. copyField(复制域)
<copyField source="cat" dest="text"/>
可以将多个Field复制到一个Field中,以便进行统一的检索。当创建索引时,solr服务器会自动的将源域的内容复制到目标域中。
l source:源域
dest:目标域,搜索时,指定目标域为默认搜索域,可以提高查询效率。
 下面例子:在ters_solr(里面包含test_name和tset_desc)中查询test_name和tset_desc描述的时候可以使用复制域配置如下

1.5. fieldType(域类型)
name:域类型的名称
class:指定域类型的solr类型。
analyzer:指定分词器。在FieldType定义的时候最重要的就是定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤。
typeindexqueryIndex 是创建索引,query是查询索引。
tokenizer:指定分词器
filter:指定过滤器
主要是配置分词器
2. 配置中文分析器
第一步导包 把中文分词器的jar包 导入\tomcat\tomcat1\webapps\solr\WEB-INF\lib
第二步在WEB-INF下创建classes(服务器会自己找到)文件夹,将扩展词和停用词还有配置文件放到里面
第三步 在solr\collection1\conf\schema.xml 中配置下面的代码
<fieldType name="text_ik" class="solr.TextField">
  <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>

3. solrj的复杂查询
3.1. solr的查询语法
1. q查询关键字,必须的。
请求的q是字符串,如果查询所有使用*:*

2. fq: (filter query)过滤查询
作用:在q查询符合结果中同时是fq查询符合的
请求fq是一个数组(多个值)
过滤查询价格从120的记录。

也可以使用*”表示无限,例如:
20以上:product_price:[20 TO *]
20以下:product_price:[* TO20]
也可以在q”查询条件中使用product_price:[1 TO 20]
如下效果和上面一样:

3. sort:排序,desc代表降序,asc代表升序
按照价格升序排

4. start:分页显示使用,开始记录下标,从0开始
rows:指定返回结果最多有多少条记录,配合start来实现分页。

5. fl: (Field List)指定返回那些字段内容,用逗号或空格分隔多个。
显示商品id、商品名称、商品分类名称

6. df:指定默认搜索Field

7. wt:  (writer type)指定输出格式,可以有xml, json, php, phps

8. hl:是否高亮 ,设置高亮Field,设置格式前缀和后缀。
 
单元测试solrj使用
//复杂查询索引
@Test
public void queryIndex2() throws Exception {
//创建连接
SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
//创建一个query对象
SolrQuery query = new SolrQuery();
//设置查询条件
query.setQuery("钻石");
//过滤条件
query.setFilterQueries("product_catalog_name:幽默杂货");
//排序条件
query.setSort("product_price", ORDER.asc);
//分页处理
query.setStart(0);
query.setRows(10);
//结果中域的列表
query.setFields("id","product_name","product_price","product_catalog_name","product_picture");
//设置默认搜索域
query.set("df", "product_keywords");
//高亮显示
query.setHighlight(true);
//高亮显示的域
query.addHighlightField("product_name");
//高亮显示的前缀
query.setHighlightSimplePre("<em>");
//高亮显示的后缀
query.setHighlightSimplePost("</em>");
//执行查询
QueryResponse queryResponse = solrServer.query(query);
//取查询结果
SolrDocumentList solrDocumentList = queryResponse.getResults();
//共查询到商品数量
System.out.println("共查询到商品数量:" + solrDocumentList.getNumFound());
//遍历查询的结果
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
//取高亮显示
String productName = "";
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
List<String> list = highlighting.get(solrDocument.get("id")).get("product_name");
//判断是否有高亮内容
if (null != list) {
productName = list.get(0);
} else {
productName = (String) solrDocument.get("product_name");
}

System.out.println(productName);
System.out.println(solrDocument.get("product_price"));
System.out.println(solrDocument.get("product_catalog_name"));
System.out.println(solrDocument.get("product_picture"));

}
}


配置solr(使用配置文件注入solr)
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:task="http://www.springframework.org/schema/task"
 xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  http://www.springframework.org/schema/mvc
  http://www.springframework.org/schema/mvc/spring-mvc-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/task
     http://www.springframework.org/schema/task/spring-task-4.0.xsd
  http://code.alibabatech.com/schema/dubbo
  http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 
  <bean id="solrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
   <constructor-arg value="http://192.168.200.128:8079/solr"/>
  </bean>
</beans>
Dao
商品对象模型:
public class ProductModel {
//商品编号
private Stringpid;
//商品名称
private Stringname;
//商品分类名称
private Stringcatalog_name;
//价格
private float price;
//商品描述
private Stringdescription;
//图片名称
private Stringpicture;
}
 
返回值对象模型
public class ResultModel {
//商品列表
private List<ProductModel>productList;
//商品总数
private LongrecordCount;
//总页数
private int pageCount;
//当前页
private int curPage;
}
@Repository
public class ProductDaoImpl implements ProductDao {

@Autowired
private SolrServer solrServer;

@Override
public ResultModel queryProduct(SolrQuery query) throws Exception {

ResultModel resultModel = new ResultModel();
//根据query对象查询商品列表
QueryResponse queryResponse = solrServer.query(query);
SolrDocumentList solrDocumentList = queryResponse.getResults();
//取查询结果的总数量
resultModel.setRecordCount(solrDocumentList.getNumFound());
List<ProductModel> productList = new ArrayList<>();
//遍历查询结果
for (SolrDocument solrDocument : solrDocumentList) {
//取商品信息
ProductModel productModel = new ProductModel();
productModel.setPid((String) solrDocument.get("id"));
//取高亮显示
String productName = "";
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
List<String> list = highlighting.get(solrDocument.get("id")).get("product_name");
if (null != list) {
productName = list.get(0);
} else {
productName = (String) solrDocument.get("product_name");
}
productModel.setName(productName);
productModel.setPrice((float) solrDocument.get("product_price"));
productModel.setCatalog_name((String) solrDocument.get("product_catalog_name"));
productModel.setPicture((String) solrDocument.get("product_picture"));
//添加到商品列表
productList.add(productModel);
}
//商品列表添加到resultmodel中
resultModel.setProductList(productList);
return resultModel;
}

}
Service
@Service
public class ProductServiceImpl implements ProductService {

@Autowired
private ProductDao productDao;

@Override
public ResultModel queryProduct(String queryString, String caltalog_name,
String price, String sort, Integer page) throws Exception {
//拼装查询条件
SolrQuery query = new SolrQuery();
//查询条件
if (null != queryString && !"".equals(queryString)) {
query.setQuery(queryString);
} else {
query.setQuery("*:*");
}
//商品分类名称过滤
if (null != caltalog_name && !"".equals(caltalog_name)) {
query.addFilterQuery("product_catalog_name:" + caltalog_name);
}
//价格区间过滤
if (null != price && !"".equals(price)) {
String[] strings = price.split("-");
query.addFilterQuery("product_price:["+strings[0]+" TO "+strings[1]+"]");
}
//排序条件
if ("1".equals(sort)) {
query.setSort("product_price", ORDER.desc);
} else {
query.setSort("product_price", ORDER.asc);
}
//分页处理
if (null == page) {
page = 1;
}
//start
int start = (page-1) * Commons.PAGE_SIZE;
query.setStart(start);
query.setRows(Commons.PAGE_SIZE);
//设置默认搜索域
query.set("df", "product_keywords");
//高亮设置
query.setHighlight(true);
query.addHighlightField("product_name");
query.setHighlightSimplePre("<span style=\"color:red\">");
query.setHighlightSimplePost("</span>");

//查询商品列表
ResultModel resultModel = productDao.queryProduct(query);
//计算总页数
long recordCount = resultModel.getRecordCount();
int pages = (int) (recordCount/Commons.PAGE_SIZE);
if (recordCount % Commons.PAGE_SIZE > 0) {
pages ++;
}
resultModel.setPageCount(pages);
resultModel.setCurPage(page);

return resultModel;
}

}
controller
@Controller
public class ProductController {

@Autowired
private ProductService productService;

@RequestMapping("/list")
public String queryProduct(String queryString, String catalog_name, String price,
String sort, Integer page, Model model) throws Exception {
//查询商品列表
ResultModel resultModel = productService.queryProduct(queryString, catalog_name, price, sort, page);
//列表传递给jsp
model.addAttribute("result", resultModel);
//参数回显
model.addAttribute("queryString", queryString);
model.addAttribute("caltalog_name", catalog_name);
model.addAttribute("price", price);
model.addAttribute("sort", sort);
model.addAttribute("page", page);

return "product_list";
}
}

原创粉丝点击