关于lucene入门以及solr和lucene的差别 可以看看我的上一篇博文 点击打开链接
什么是solr
Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。
Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中,Solr 索引的实现方法很简单,用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr根据xml文档添加、删除、更新索引 。Solr 搜索只需要发送 HTTP GET 请求,然后对 Solr 返回Xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。
基于Solr实现站内搜索扩展性较好并且可以减少程序员的工作量,因为Solr提供了较为完备的搜索引擎解决方案,因此在门户、论坛等系统中常用此方案。
Solr的下载
从Solr官方网站(http://lucene.apache.org/solr/ )下载Solr4.10.3(也可以下载新版,我现在用的是这个版本),根据Solr的运行环境,Linux下需要下载lucene-4.10.3.tgz,windows下需要下载lucene-4.10.3.zip。
Solr使用指南可参考:https://wiki.apache.org/solr/FrontPage。
运行环境
solr 需要运行在一个Servlet容器中,Solr4.10.3要求jdk使用1.7以上,Solr默认提供Jetty(java写的Servlet容器),本文使用Tocmat作为Servlet容器,环境如下:
整合步骤
第一步:安装tomcat。
第二步:把solr的war包复制到tomcat 的webapp目录下。
把\solr-4.10.3\dist\solr-4.10.3.war复制到tomcat\webapps下。改名为solr.war
第三步:solr.war解压。使用压缩工具解压或者启动tomcat自动解压。解压之后删除solr.war
第四步:把\solr-4.10.3\example\lib\ext目录下的所有的jar包添加到solr工程中
第五步:配置solrHome和solrCore。
1)创建一个solrhome(存放solr所有配置文件的一个文件夹)。\solr-4.10.3\example\solr目录就是一个标准的solrhome。
2)把\solr-4.10.3\example\solr文件夹复制到D:\temp\0108路径下,改名为solrhome,改名不是必须的,是为了便于理解。
3)在solrhome下有一个文件夹叫做collection1这就是一个solrcore。就是一个solr的实例。一个solrcore相当于mysql中一个数据库。Solrcore之间是相互隔离。
新增solrcore 复制之前的 然后改一下properties文件
第六步:告诉solr服务器配置文件也就是solrHome的位置。修改web.xml使用jndi的方式告诉solr服务器。
注意事项
tomcat必须是重新解压的 然后之前一直没有启动成功是因为文件夹名为 lucene&solr 改为lucene_solr就成功了
solr不用默认的家(solrhome) 自己建个 , 因为要搭建集群 默认的一个是不够的
集群的目的就是防止你挂掉不能用 防止你存储索引过多 存不下
在tomcat的solr中web.xml里更改家的地址 <env-entry> 被注释注释了 更改<env-entry-value> 改为手动的地址
启动tomcat 浏览器中输入http://localhost:8080/solr 就可以进入solr页面了
这个界面以后验证时用到 后面会说具体怎么运用
安装中文分词器
使用IKAnalyzer中文分析器。
第一步:把IKAnalyzer2012FF_u1.jar添加到solr/WEB-INF/lib目录下。
第二步:复制IKAnalyzer的配置文件和自定义词典和停用词词典到solr的classpath下。
第三步:在schema.xml中添加一个自定义的fieldType,使用中文分析器。
<!-- IKAnalyzer--> <fieldType name="text_ik" class="solr.TextField"> <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/> </fieldType> |
第四步:定义field,指定field的type属性为text_ik
<!--IKAnalyzer Field--> <field name="title_ik" type="text_ik" indexed="true" stored="true" /> <field name="content_ik" type="text_ik" indexed="true" stored="false" multiValued="true"/> |
第四步:重启tomcat
设置业务系统Field
如果不使用Solr提供的Field可以针对具体的业务需要自定义一套Field,如下是商品信息Field:
<!--product-->
<field name="product_name" type="text_ik" indexed="true" stored="true"/>
<field name="product_price" type="float" indexed="true" stored="true"/>
<field name="product_description" type="text_ik" indexed="true" stored="false" />
<field name="product_picture" type="string" indexed="false" stored="true" />
<field name="product_catalog_name" type="string" indexed="true" stored="true" />
也是放在 schema.xml中 如果你知道lucene,就会发现其实这就和lucene的语法一样 毕竟是基于lucene封装的
Solr管理索引库
批量导入数据
使用dataimport插件批量导入数据。
第一步:把dataimport插件依赖的jar包添加到solrcore(collection1\lib)中
H:\lucene_solr\solr\solr-4.10.3\dist中的
solr-dataimporthandler-4.10.3.jar和solr-dataimporthandler-extras-4.10.3.jar
还需要对应的(mysql)的数据库驱动
第二步:配置solrconfig.xml文件,添加一个requestHandler。
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler"> <lst name="defaults"> <str name="config">data-config.xml</str> </lst> </requestHandler> |
第三步:创建一个data-config.xml,保存到collection1\conf\目录下
<?xml version="1.0" encoding="UTF-8" ?> <dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/lucene" user="root" password="1234"/> <document> <entity name="product" query="SELECT pid,name,catalog_name,price,description,picture FROM products "> <field column="pid" name="id"/> <field column="name" name="product_name"/> <field column="catalog_name" name="product_catalog_name"/> <field column="price" name="product_price"/> <field column="description" name="product_description"/> <field column="picture" name="product_picture"/> </entity> </document>
</dataConfig> |
这里是要对应数据库表中导入的数据 值得一提的是 solr中必须有id (string类型)而且id是自己设置的 不是lucene中自增
第四步:重启tomcat
第五步:点击“execute”按钮导入数据
到入数据前会先清空索引库,然后再导入。
删除文档
删除索引格式如下:
1) 删除制定ID的索引
<delete>
<id>8</id>
</delete>
<commit/>
2) 删除查询到的索引数据
<delete>
<query>product_catalog_name:幽默杂货</query>
</delete>
3) 删除所有索引数据
<delete>
<query>*:*</query>
</delete>
查询索引
通过/select搜索索引,Solr制定一些参数完成不同需求的搜索:
1. q - 查询字符串,必须的,如果查询所有使用*:*。
2. fq - (filter query)过虑查询,作用:在q查询符合结果中同时是fq查询符合的,
也可以在“q”查询条件中使用product_price:[1 TO 20],
也可以使用“*”表示无限,例如:
20以上:product_price:[20 TO *]
20以下:product_price:[* TO 20]
3. sort - 排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]…
4. start - 分页显示使用,开始记录下标,从0开始
5. rows - 指定返回结果最多有多少条记录,配合start来实现分页。
6. fl - 指定返回那些字段内容,用逗号或空格分隔多个。
7. df-指定一个搜索Field
也可以在SolrCore目录 中conf/solrconfig.xml文件中指定默认搜索Field,指定后就可以直接在“q”查询条件中输入关键字。
8. wt - (writer type)指定输出格式,可以有 xml, json, php, phps, 后面 solr 1.3增加的,要用通知我们,因为默认没有打开。
9. hl 是否高亮 ,设置高亮Field,设置格式前缀和后缀。
使用SolrJ管理索引库
solrj是访问Solr服务的java客户端,提供索引和搜索的请求方法
jar包代码实现
package com.solrj;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
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.apache.solr.common.params.SolrParams;
import org.junit.Test;
/**
*
*solrj管理
*添加
*删除
*修改
*查询
*
*@author yingzhi
*
*@version 2018年1月27日下午4:22:14
*
*/
public class SolrJManager {
//添加
@Test
public void testAdd() throws Exception{
//http://localhost:8080/solr/collection2 在核2添加 不写默认核1
String baseURL = "http://localhost:8080/solr";
//单机版
SolrServer solrServer = new HttpSolrServer(baseURL);
SolrInputDocument doc = new SolrInputDocument();
doc.setField("id", "haha");
doc.setField("name", "范冰冰");
//添加
solrServer.add(doc);
solrServer.commit();
}
//删除
@Test
public void testDelete() throws Exception{
String baseURL = "http://localhost:8080/solr";
//单机版
SolrServer solrServer = new HttpSolrServer(baseURL);
//删除全部
solrServer.deleteByQuery("*:*",1000);
}
//更新
@Test
public void testUpdate() throws Exception{
String baseURL = "http://localhost:8080/solr";
//单机版
SolrServer solrServer = new HttpSolrServer(baseURL);
//更新
//和添加一样 id不同就是添加 相同就是更新
}
//查询
@Test
public void testSearch() throws Exception{
String baseURL = "http://localhost:8080/solr";
//单机版
SolrServer solrServer = new HttpSolrServer(baseURL);
//查询 关键词 台灯 过滤条件 "product_catalog_name": "幽默杂货", "product_price": 18.9,
//价格排序 高亮 默认域 分页 开始行 每页数 只查询指定域
SolrQuery solrQuery = new SolrQuery();
//关键词 限定条件在这加
//solrQuery.set("q", "*:*");
//solrQuery.set("q", "product_name:台灯");
solrQuery.setQuery("product_name:台灯"); //等价上面的
//过滤条件 "product_catalog_name": "幽默杂货"
solrQuery.set("fq","product_price:[* TO 10]");
//价格排序
solrQuery.addSort("product_price",ORDER.desc);
//分页
solrQuery.setStart(0);
solrQuery.setRows(5);
// 默认域
solrQuery.set("df","product_name");
//只查询指定域
solrQuery.set("fl", "id,product_name");
//高亮 后面还得配置
//打开开关
solrQuery.setHighlight(true);
//指定高亮域
solrQuery.addHighlightField("product_name");
//前缀 后缀
solrQuery.setHighlightSimplePre("<span style='color:red'>");
solrQuery.setHighlightSimplePost("</span>");
//执行查询
QueryResponse response = solrServer.query(solrQuery);
//文档结果集
SolrDocumentList docs = response.getResults();
//for循环里 给每个添加
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
//Map K id V Map
//Map k 域名 V List
//List list.get(0)
//总条数
long numFound = docs.getNumFound();
System.out.println(numFound);
/*"product_picture": "2014032613103438.png",
"product_catalog_name": "幽默杂货",
"product_price": 18.9,
"product_name": "花儿朵朵彩色金属门后挂 8钩免钉门背挂钩2066",
"id": "1",*/
for (SolrDocument doc : docs) {
System.out.println(doc.get("id"));
System.out.println(doc.get("product_picture"));
System.out.println(doc.get("product_catalog_name"));
System.out.println(doc.get("product_price"));
System.out.println(doc.get("product_name"));
System.out.println("-----------------------------");
Map<String, List<String>> map = highlighting.get(doc.get("id"));
//给每个名字标高亮
List<String> list = map.get("product_name");
System.out.println(list.get(0));
}
}
}