solr

什么是 solr
Solr Apache 下的一个顶级开源项目,采用 Java 开发,它是基于 Lucene 全文搜索服务 Solr 可以独立运行在 Jetty Tomcat 等这些 Servlet 容器中。
使用 Solr 进行创建索引和搜索索引的实现方法很简单,如下:
创建索引:客户端(可以是浏览器可以是 Java 程序)用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档, Solr 服务器根据 xml 文档添加、删除、更新索引 。
搜索索引:客户端(可以是浏览器可以是 Java 程序)用 GET 方法向 Solr 服务器发送请求,然后对 Solr 服务器返回 Xml json 等格式的查询结果进行解析。 Solr 不提供构建页面 UI 的功能。 Solr 提供了一个管理界面,通过管理界面可以查询 Solr 的配置和运行情况。
Solr 是一个可以独立运行的搜索服务器,使用 solr 进行全文检索服务的话,只需要通过 http 请求访问该服务器即可。
S olr Lucene 的区别
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 文件进行复制
粘贴到 Tomcat webapps solr WEB-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 文件在 SolrCore conf 目录下,在此配置文件中定义了域以及域的类型等一些配置。在 solr 中域必须先定义后使用。
1.1. field
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
Name :域的名称
Type :域的类型
Indexed :是否索引
Stored :是否存储
Required :是否必须
multiValued :是否是多值,存储多个值时设置为 true solr 允许一个 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 ,包括分词和过滤。
type index query I ndex   是创建索引, 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 是一个数组(多个值)
过滤查询价格从 1 20 的记录。

也可以使用 * ”表示无限,例如:
20 以上: product_price:[20 TO *]
20 以下: product_price:[ *  TO 20 ]
也可以在 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 String pid;
// 商品名称
private String name;
// 商品分类名称
private String catalog_name;
// 价格
private  float  price;
// 商品描述
private String description;
// 图片名称
private String picture;
}
 
返回值对象模型
public  class ResultModel {
// 商品列表
private List<ProductModel> productList;
// 商品总数
private Long recordCount;
// 总页数
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";
}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值