Solr是apache的顶级开源项目,它是使用java开发 ,基于lucene的全文检索服务器。php
Solr比lucene提供了更多的查询语句,并且它可扩展、可配置,同时它对lucene的性能进行了优化。java
Solr是如何实现全文检索的呢?mysql
索引流程:solr客户端(浏览器、java程序)能够向solr服务端发送POST请求,请求内容是包含Field等信息的一个xml文档,经过该文档,solr实现对索引的维护(增删改)web
搜索流程:solr客户端(浏览器、java程序)能够向solr服务端发送GET请求,solr服务器返回一个xml文档。sql
Solr一样没有视图渲染的功能。数据库
Lucene 是一个全文检索引擎工具包,它是一个 jar 包,不能独立运行,对外提供服务。apache
Solr 是一个全文检索服务器,它能够单独运行在 servlet 容器,能够单独对外提供搜索和索引功能。Solr 比 lucene 在开发全文检索功能时,更快捷、更方便。 json
solr 和 lucene 的版本时同步更新的,最新版本是5.2.1数组
下载地址:http://archive.apache.org/dist/lucene/solr/浏览器
jdk:1.7及以上 solr:4.10.3 mysql:5x web服务器:tomcat7
Solrhome是solr服务运行的主目录,一个solrhome目录里面包含多个solrcore目录,一个solrcore目录里面了一个solr实例运行时所须要的配置文件和数据文件。
每个solrcore均可以单独对外提供搜索和索引服务。 多个solrcore之间没有关系。
solrhome: solr-4.10.3\example\solr solrcore: solr-4.10.3\example\solr\collection1 包含配置文件,索引文件日志信息
安装 solrcore 须要先安装 solrhome 将上面solrhome下的文件拷贝到web.xml中指定的solrhome中便可
配置 solrcore 的 conf 目录下的 solrconfig.xml 配置文件,来配置 solrcore 的运行信息。
在该文件中,主要配置三个标签:lib 标签、datadir标签、requestHandler 标签。
solrcore 须要添加一个扩展依赖包,经过 lib 标签来指定依赖包的地址
solr.install.dir 表示 solrcore 的安装目录
拷贝 example 目录下的 contrib 和 dis 目录到
修改 lib 标签
每一个 solrcore 都有本身的索引文件目录,默认在 solrcore 目录下的 data 中。
data数据目录下包括了index索引目录 和tlog日志文件目录。 若是不想使用默认的目录也能够经过solrConfig.xml更改索引目录 ,以下:
requestHandler 请求处理器,定义索引和搜索的访问方式。 经过 /update 维护索引,能够完成对索引的添加、修改、删除操做。
经过 /select 搜索索引
<requestHandler name="/select" class="solr.SearchHandler">
<!-- 设置默认的参数值,能够在请求地址中修改这些参数-->
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int><!--显示数量-->
<str name="wt">json</str><!--显示格式-->
<str name="df">text</str><!--默认搜索字段-->
</lst>
</requestHandler>
复制代码
仪表盘,显示 solr 实例运行时间、版本、系统资源、jvm等信息。 、
solr 运行日志信息
Cloud即SolrCloud,即Solr云(集群),当使用Solr Cloud模式运行时会显示此菜单.
solrcore 的管理界面,这里能够添加 solrcore 实例。
solr 在 jvm 运行环境中的属性信息。
显示 solr server 中当前活跃线程信息,同时也能够跟踪线程运行栈信息。
选择一个 solrcore 进行详细操做,以下:
经过此界面能够测试索引分析器和搜索分析器的执行状况。 注:solr 中,分析器是绑定在域类型中的。
能够定义数据导入处理器,从关系数据库导入到 solr 索引库中。默认配置,须要手工配置。
经过 /update 表示更新索引,solr 默认根据 id(惟一约束) 域来更新 document 的内容,若是根据 id 值搜索不到 id 域则会执行添加操做,若是找到则更新。
经过此菜单能够建立索引、更新索引、删除索引等操做,界面以下:
经过/select执行搜索索引,必须指定“q”查询条件方可搜索。
配置多solrcore的好处: 一、在进行 solrcloud 的时候,必须配置多solrcore 二、每一个 solrcore 之间是独立的,均可以单独对外提供服务。不一样的业务模块能够使用不一样的solrcore 来提供搜索和索引服务。
添加
在 schema.xml 文件中,主要配置了 solrcore 的一些数据信息,包括 Field 和 FieldType 的定义等信息,在 solr 中,Field 和 FieldType 都须要先定义后使用。
定义Field域
Name:指定域的名称 Type:指定域的类型 Indexed:是否索引 Stored:是否存储 Required:是否必须 multiValued:是否多值,好比商品信息中,一个商品有多张图片,一个Field像存储多个值的话,必须将multiValued设置为true。
动态域
Name:指定动态域的命名规则
指定惟一键
id
其中的id是在Field标签中已经定义好的域名,并且该域要设置为required为true。
一个schema.xml文件中必须有且仅有一个惟一键
复制域
Source:要复制的源域的域名 Dest:目标域的域名
由dest指的的目标域,必须设置multiValued为true。
定义域的类型
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<!-- in this example, we will only use synonyms at query time <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/> -->
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
复制代码
Name:指定域类型的名称 Class:指定该域类型对应的solr的类型 Analyzer:指定分析器 Type:index、query,分别指定搜索和索引时的分析器 Tokenizer:指定分词器 Filter:指定过滤器
使用ikanalyzer进行中文分词
第一步:将ikanalyzer的jar包拷贝到如下目录
第二步:将ikanalyzer的扩展词库的配置文件拷贝到 目录
配置 FieldType
配置使用中文分词的 field
重启 tomcat
对京东案例中的 products 表的数据进行索引,因此须要定义对应的 field 域。
须要往索引库添加的字段有: pid、name、catalog、catalog_name、price、description、picture
FieldType: 经分析,因为中文分词器已经配置完FieldType,因此目前FieldType已经知足须要,无需配置。
Field: Pid: 因为pid在products表中是惟一键,并且在solr的shema.xml中已有一个id的惟一键配置,因此不须要再从新定义pid域。
Name:
<!-- 商品名称 -->
<field name="product_name" type="text_ik" indexed="true" stored="true"/>
复制代码
Catalog、catalog_name:
<!-- 商品分类ID -->
<field name="product_catalog" type="string" indexed="true" stored="true"/>
<!-- 商品分类名称 -->
<field name="product_catalog_name" type="string" indexed="true" stored="false"/>
复制代码
Price:
<!-- 商品价格 -->
<field name="product_price" type="float" indexed="true" stored="true"/>
复制代码
Description:
<!-- 商品描述 -->
<field name="product_description" type="text_ik" indexed="true" stored="false"/>
复制代码
Picture:
<!-- 商品图片地址 -->
<field name="product_picture" type="string" indexed="false" stored="true"/>
复制代码
<!-- 目标域 -->
<field name="product_keywords" type="text_ik" indexed="true" stored="true" multiValued="true"/>
<!-- 将商品名称添加到目标域 -->
<copyField source="product_name" dest="product_keywords"/>
<!-- 将商品描述添加到目标域 -->
<copyField source="product_description" dest="product_keywords"/>
复制代码
该插件能够将数据库中指定的sql语句的结果导入到solr索引库中。
第一步:添加 jar 包 Dataimport的jar包(solr-4.10.3\dist\solr-dataimporthandler-extras-4.10.3.jar) 复制到
<lib dir="${solr.install.dir:../..}/contrib/dataimporthandler/lib" regex=".*\.jar" />
mysql 数据库驱动包 复制 mysql 驱动包到:
<lib dir="${solr.install.dir:../..}/contrib/db/lib" regex=".*\.jar" />
第二步:配置 requesthandler 在 solrconfig.xml 中,添加一个 dataimport 的 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
在 solrconfig.xml 同级目录下,建立 data-config.xml

```xml
<dataConfig>
<dataSource
type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/taotao"
user="root"
password="root"/>
<document>
<entity name="products" query="select pid,name,catalog,catalog_name,price,description,picture from products ">
<field column="pid" name="id" />
<field column="name" name="product_name" />
<field column="catalog" name="product_catalog" />
<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>
复制代码
solrj 就是 solr 服务器的 java 客户端
jdk ide tomcat solrj
solrj 的依赖包和核心包
solrj 的扩展服务包
在solr中,索引库中都会存在一个惟一键,若是一个Document的id存在,则执行修改操做,若是不存在,则执行添加操做。
@Test
public void insertAndUpdateIndex() throws Exception {
// 建立HttpSolrServer
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
// 建立Document对象
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", "c001");
doc.addField("name", "solr test111");
// 将Document对象添加到索引库
server.add(doc);
// 提交
server.commit();
}
复制代码
@Test
public void deleteIndex() throws Exception {
// 建立HttpSolrServer
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
// 根据指定的ID删除索引
// server.deleteById("c001");
// 根据条件删除
server.deleteByQuery("id:c001");
// 删除所有(慎用)
server.deleteByQuery("*:*");
// 提交
server.commit();
}
复制代码
@Test
public void search01() throws Exception {
// 建立HttpSolrServer
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
// 建立SolrQuery对象
SolrQuery query = new SolrQuery();
// 输入查询条件
query.setQuery("product_name:小黄人");
// 执行查询并返回结果
QueryResponse response = server.query(query);
// 获取匹配的全部结果
SolrDocumentList list = response.getResults();
// 匹配结果总数
long count = list.getNumFound();
System.out.println("匹配结果总数:" + count);
for (SolrDocument doc : list) {
System.out.println(doc.get("id"));
System.out.println(doc.get("product_name"));
System.out.println(doc.get("product_catalog"));
System.out.println(doc.get("product_price"));
System.out.println(doc.get("product_picture"));
System.out.println("=====================");
}
}
复制代码
solr的查询语法
1.q - 查询关键字,必须的,若是查询全部使用*:*
。 请求的q是字符串
2.fq - (filter query)过虑查询,做用:在q查询符合结果中同时是fq查询符合的,例如:: 请求fq是一个数组(多个值)
3.sort - 排序,格式:sort=+<desc|asc>[,+<desc|asc>]… 。示例:
4.start - 分页显示使用,开始记录下标,从0开始
5.rows - 指定返回结果最多有多少条记录,配合start来实现分页。 实际开发时,知道当前页码和每页显示的个数最后求出开始下标。
6.fl - 指定返回那些字段内容,用逗号或空格分隔多个。
7.df-指定一个搜索Field
8.wt - (writer type)指定输出格式,能够有 xml, json, php, phps, 后面 solr 1.3增长的,要用通知咱们,由于默认没有打开。
9.hl 是否高亮 ,设置高亮Field,设置格式前缀和后缀。
代码
@Test
public void search02() throws Exception {
// 建立HttpSolrServer
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
// 建立SolrQuery对象
SolrQuery query = new SolrQuery();
// 输入查询条件
query.setQuery("product_name:小黄人");
// query.set("q", "product_name:小黄人");
// 设置过滤条件
// 若是设置多个过滤条件的话,须要使用query.addFilterQuery(fq)
query.setFilterQueries("product_price:[1 TO 10]");
// 设置排序
query.setSort("product_price", ORDER.asc);
// 设置分页信息(使用默认的)
query.setStart(0);
query.setRows(10);
// 设置显示的Field的域集合
query.setFields("id,product_name,product_catalog,product_price,product_picture");
// 设置默认域
query.set("df", "product_keywords");
// 设置高亮信息
query.setHighlight(true);
query.addHighlightField("product_name");
query.setHighlightSimplePre("<em>");
query.setHighlightSimplePost("</em>");
// 执行查询并返回结果
QueryResponse response = server.query(query);
// 获取匹配的全部结果
SolrDocumentList list = response.getResults();
// 匹配结果总数
long count = list.getNumFound();
System.out.println("匹配结果总数:" + count);
// 获取高亮显示信息
Map<String, Map<String, List<String>>> highlighting = response
.getHighlighting();
for (SolrDocument doc : list) {
System.out.println(doc.get("id"));
List<String> list2 = highlighting.get(doc.get("id")).get(
"product_name");
if (list2 != null)
System.out.println("高亮显示的商品名称:" + list2.get(0));
else {
System.out.println(doc.get("product_name"));
}
System.out.println(doc.get("product_catalog"));
System.out.println(doc.get("product_price"));
System.out.println(doc.get("product_picture"));
System.out.println("=====================");
}
}
复制代码