Solr 全文搜索服务

来源:互联网 发布:ktv盈利数据 编辑:程序博客网 时间:2024/05/16 14:52

 Solr

全文搜索服务

 

  


1     Solr介绍


1.1     什么是solr


Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器Solr可以独立运行在Jetty、Tomcat等这些Servlet容器中。

Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化

使用Solr 进行创建索引和搜索索引的实现方法很简单,如下:

* 创建索引:客户端(可以是浏览器可以是Java程序)用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr服务器根据xml文档添加、删除、更新索引 。

* 搜索索引:客户端(可以是浏览器可以是Java程序)用 GET方法向 Solr 服务器发送请求,然后对Solr服务器返回Xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建页面UI的功能,但是Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况

 

1.2     Solr和Lucene的区别

Lucene是一个开放源代码的全文检索引擎工具包,它不是一个完整的全文检索应用。Lucene仅提供了完整的查询引擎和索引引擎,目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者以Lucene为基础构建全文检索应用。

 Solr的目标是打造一款企业级的搜索引擎系统,它是基于Lucene一个搜索引擎服务,可以独立运行,通过Solr可以非常快速的构建企业的搜索引擎,通过Solr也可以高效的完成站内搜索功能。



2     Solr安装配置


2.1     下载solr


Solr和lucene的版本是同步更新的,最新的版本是5.2.1

本课程使用的版本:4.10.3

 

下载地址:http://archive.apache.org/dist/lucene/solr/

下载版本:4.10.3

Linux下需要下载lucene-4.10.3.tgzwindows下需要下载lucene-4.10.3.zip

 

下载lucene-4.10.3.zip并解压:

bin:solr的运行脚本

contrib:solr的一些扩展jar包,用于增强solr的功能。

dist:该目录包含build过程中产生的war和jar文件,以及相关的依赖文件。

docs:solr的API文档

example:solr工程的例子目录:

example/solr

         该目录是一个标准的SolrHome,它包含一个默认的SolrCore

l  example/multicore

         该目录包含了在Solr的multicore中设置的多个Core目录。

example/webapps

    该目录中包括一个solr.war,该war可作为solr的运行实例工程。

licenses:solr相关的一些许可信息

 


 

2.2     运行环境



solr 需要运行在一个Servlet容器中,Solr4.10.3要求jdk使用1.7以上,Solr默认提供Jetty(java写的Servlet容器),本教程使用Tocmat作为Servlet容器,相关环境如下:

 

l  Solr:4.10.3

l  Jdk环境:1.7.0_72(solr4.10 不能使用jdk1.7以下

l  Web服务器(servlet容器):Tomcat 7X

 

2.3     SolrCore配置



2.3.1 SolrHome和SolrCore



SolrHome是Solr运行的主目录,该目录中包括了多个SolrCore目录。SolrCore目录中包含了运行Solr实例所有的配置文件和数据文件,Solr实例就是SolrCore

一个SolrHome可以包括多个SolrCore(Solr实例),每个SolrCore提供单独的搜索和索引服务。



2.3.2 目录结构

SolrHome目录:


SolrCore目录:




2.3.3 创建SolrCore


创建SolrCore先要创建SolrHome。在solr解压包下solr-4.10.3\example\solr文件夹就是一个标准的SolrHome。

 

l  拷贝solr解压包下solr-4.10.3\example\solr文件夹。



l  复制该文件夹到本地的一个目录,把文件名称改为solrhome。

注:改名不是必须的,只是为了便于理解


 

l  打开SolrHome目录


SolrCore创建成功。



2.3.4 配置SolrCore


在conf文件夹下有一个solrconfig.xml。这个文件是来配置SolrCore实例的相关信息。如果使用默认配置可以不用做任何修改。它里面包含了不少标签,但是我们关注的标签为:lib标签、datadir标签、requestHandler标签

 

2.3.4.1  lib 标签

在solrconfig.xml中可以加载一些扩展的jar,solr.install.dir表示solrCore的目录位置,需要如下修改:

 

然后将contribdist两个目录拷贝到E:\12-solr\0505


2.3.4.2  datadir标签

每个SolrCore都有自己的索引文件目录 ,默认在SolrCore目录下的data中。


data数据目录下包括了index索引目录 和tlog日志文件目录。

如果不想使用默认的目录也可以通过solrConfig.xml更改索引目录 ,如下:

 


2.3.4.3  requestHandler标签

requestHandler请求处理器,定义了索引和搜索的访问方式。

通过/update维护索引,可以完成索引的添加、修改、删除操作。


提交xml、json数据完成索引维护,索引维护小节详细介绍。

 

 

通过/select搜索索引。


设置搜索参数完成搜索,搜索参数也可以设置一些默认值,如下:

 

<requestHandlername="/select" class="solr.SearchHandler">

    <!-- 设置默认的参数值,可以在请求地址中修改这些参数-->

    <lst name="defaults">

        <strname="echoParams">explicit</str>

        <intname="rows">10</int><!--显示数量-->

        <str name="wt">json</str><!--显示格式-->

        <strname="df">text</str><!--默认搜索字段-->

    </lst>

</requestHandler>

 

2.4     Solr工程部署


由于在项目中用到的web服务器大多数是用的Tomcat,所以就讲solr和Tomcat的整合。



2.4.1 安装Tomcat

2.4.2 把solr.war部署到Tomcat中

1、 从solr解压包下的solr-4.10.3\example\webapps目录中拷贝solr.war



2、 复制到tomcat安装目录的webapps文件夹下



2.4.3 解压缩solr.war

使用压缩工具解压或者启动tomcat自动解压。解压之后删除solr.war

2.4.4 添加solr服务的扩展依赖包(日志包)

l  把solr解压包下的solr-4.10.3\example\lib\ext目录下的所有jar包拷贝。


l  复制到解压缩后的solr工程的WEB-INF\lib目录


 

2.4.5 添加log4j.properties

1、 把solr解压包下solr-4.10.3\example\resources\log4j.properties文件进行拷贝


2、 在解压缩后的solr工程中的WEB-INF目录中创建classes文件夹


 

3、 复制log4j.properties文件到刚创建的classes目录

 



2.4.6 在solr应用的web.xml文件中,加载SolrHome

修改web.xml使用jndi的方式告诉solr服务器。

Solr/home名称必须是固定的。

 

 

2.4.7 启动Tomcat进行访问

访问http://localhost:8080/solr/

出现以下界面则说明solr安装成功!!!

 

 

2.5     管理界面功能介绍


2.5.1 Dashboard

仪表盘,显示了该Solr实例开始启动运行的时间、版本、系统资源、jvm等信息。

2.5.2 Logging

Solr运行日志信息

2.5.3 Cloud

Cloud即SolrCloud,即Solr云(集群),当使用SolrCloud模式运行时会显示此菜单,该部分功能在第二个项目,即电商项目会讲解。

2.5.4 Core Admin

Solr Core的管理界面。在这里可以添加SolrCore实例。

2.5.5 java properties

Solr在JVM 运行环境中的属性信息,包括类路径、文件编码、jvm内存设置等信息。

2.5.6 Tread Dump

显示Solr Server中当前活跃线程信息,同时也可以跟踪线程运行栈信息。

2.5.7 Core selector(重点)

选择一个SolrCore进行详细操作,如下:


2.5.7.1  Analysis(重点)


通过此界面可以测试索引分析器和搜索分析器的执行情况。

注:solr中,分析器是绑定在域的类型中的

 

2.5.7.2  dataimport

可以定义数据导入处理器,从关系数据库将数据导入到Solr索引库中。

默认没有配置,需要手工配置。

2.5.7.3  Document(重点)

通过/update表示更新索引,solr默认根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新

 

通过此菜单可以创建索引、更新索引、删除索引等操作,界面如下:

 

l  overwrite="true" : solr在做索引的时候,如果文档已经存在,就用xml中的文档进行替换

l  commitWithin="1000" : solr 在做索引的时候,每个1000(1秒)毫秒,做一次文档提交。为了方便测试也可以在Document中立即提交,</doc>后添加“<commit/>”

2.5.7.4  Query(重点)

通过/select执行搜索索引,必须指定“q”查询条件方可搜索。

 

 

2.6     多solrcore配置

配置多SolrCore的好处:

1.      一个solr工程对外通过SorlCore 提供服务,每个SolrCore相当于一个数据库,这个功能就相当于一个MySQL可以运行多个数据库。

2.      将索引数据分SolrCore存储,方便对索引数据管理维护。

3.      SolrCloud集群需要使用多core。

 

 

复制原来的core目录为collection2,目录结构如下:


修改collection2下的core.properties,如下:


演示多core的使用,在collection1和collection2中分别创建索引、搜索索引。

 

 

3     solr基本使用


3.1     schema.xml

schema.xml文件在SolrCore的conf目录下,它是Solr数据表配置文件,在此配置文件中定义了域以及域的类型还有其他一些配置,solr中域必须先定义后使用

3.1.1 field

<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />

l  Name:域的名称

l  Type:域的类型

l  Indexed:是否索引

l  Stored:是否存储

l  Required:是否必须

l  multiValued:是否是多值,存储多个值时设置为true,solr允许一个Field存储多个值,比如存储一个用户的好友id(多个),商品的图片(多个,大图和小图)

3.1.2 fieldType(域类型)

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">  
  2.   <analyzer type="index">  
  3.     <tokenizer class="solr.StandardTokenizerFactory"/>  
  4.     <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />  
  5.     <!-- in this example, we will only use synonyms at query time  
  6.     <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>  
  7.     -->  
  8.     <filter class="solr.LowerCaseFilterFactory"/>  
  9.   </analyzer>  
  10.   <analyzer type="query">  
  11.     <tokenizer class="solr.StandardTokenizerFactory"/>  
  12.     <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />  
  13.     <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>  
  14.     <filter class="solr.LowerCaseFilterFactory"/>  
  15.   </analyzer>  
  16. </fieldType>  


l  name:域类型的名称

l  class:指定域类型的solr类型。

l  analyzer:指定分词器。在FieldType定义的时候最重要的就是定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤。

l  type:index和query。Index 是创建索引,query是查询索引。

l  tokenizer:指定分词器

l  filter:指定过滤器

3.1.3 uniqueKey

<uniqueKey>id</uniqueKey>

相当于主键,每个文档中必须有一个id域。

3.1.4 copyField(复制域)

<copyField source="cat" dest="text" />

可以将多个Field复制到一个Field中,以便进行统一的检索。当创建索引时,solr服务器会自动的将源域的内容复制到目标域中。

l  source:源域

l  dest:目标域,搜索时,指定目标域为默认搜索域,可以提供查询效率。

 

定义目标域:


必须要使用:multiValued="true"

 

3.1.5 dynamicField(动态域)

<dynamicField  name="*_i"  type="int"  indexed="true"  stored="true"/>

l  Name:动态域的名称,是一个表达式,*匹配任意字符,只要域的名称和表达式的规则能够匹配就可以使用。

 

例如:搜索时查询条件【product_i:钻石】就可以匹配这个动态域,可以直接使用,不用单独再定义一个product_i


3.2     配置中文分析器

使用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

测试:


3.3     配置业务field


3.3.1 需求

要使用solr实现电商网站中商品搜索。

 

电商中商品信息在mysql数据库中存储了,将mysql数据库中数据在solr中创建索引。

 

需要在solr的schema.xml文件定义商品Field。

 

3.3.2 定义步骤

 

先确定定义的商品document的field有哪些?

可以根据mysql数据库中商品表的字段来确定:

 

products商品表:


商品document的field包括:pid、name、catalog、catalog_name、price、description、picture

 

 

先定义Fieldtype:

solr本身提供的fieldtype类型够用了不用定义新的了。

 

 

 

再定义Field:

 

pid:商品id主键

使用solr本身提供的:

<field name="id"type="string" indexed="true" stored="true"required="true" multiValued="false" />

 

name:商品名称

<field name="product_name"type="text_ik" indexed="true" stored="true"/>

 

catalog:商品分类

<field name="product_catalog"type="string" indexed="true" stored="true"/>

 

catalog_name:商品分类名称

<field name="product_catalog_name"type="text_ik" indexed="true" stored="true"/>

 

price:商品价格

<fieldname="product_price" type="float" indexed="true"stored="true"/>

 

description:商品描述

<fieldname="product_description" type="text_ik"indexed="true" stored="false"/>

 

picture:商品图片

<field name="product_picture"type="string" indexed="false" stored="true"/>

 

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <!--product-->  
  2. <field name="product_name" type="text_ik" indexed="true" stored="true"/>  
  3. <field name="product_catalog" type="string" indexed="true" stored="true"/>  
  4. <field name="product_catalog_name" type="string" indexed="true" stored="true" />  
  5. <field name="product_price"  type="float" indexed="true" stored="true"/>  
  6. <field name="product_description" type="text_ik" indexed="true" stored="false" />  
  7. <field name="product_picture" type="string" indexed="false" stored="true" />  
  8. <field name="product_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>  



3.4     dataimportHandler插件

3.4.1 第一步:添加jar包

l  Dataimport的jar

从solr-4.10.3\dist目录下拷贝solr-dataimporthandler-4.10.3.jar,复制到以下目录:


修改schema.xml如下:


 

l  数据库驱动包

把mysql数据库驱动包,拷贝到以下目录:


修改schema.xml,如下:


 

 

3.4.2 第二步:配置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> 

 

3.4.3 第三步:创建一个data-config.xml


在collection1\conf\目录下创建data-config.xml文件

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>    
  2. <dataConfig>     
  3. <dataSource type="JdbcDataSource"     
  4.           driver="com.mysql.jdbc.Driver"     
  5.           url="jdbc:mysql://localhost:3306/solr"     
  6.           user="root"     
  7.           password="root"/>     
  8. <document>     
  9.     <entity name="product" query="SELECT pid,name,catalog,catalog_name,price,description,picture FROM products ">  
  10.          <field column="pid" name="id"/>   
  11.          <field column="name" name="product_name"/>   
  12. <field column="catalog" name="product_catalog"/>  
  13.          <field column="catalog_name" name="product_catalog_name"/>   
  14.          <field column="price" name="product_price"/>   
  15.          <field column="description" name="product_description"/>   
  16.          <field column="picture" name="product_picture"/>   
  17.     </entity>     
  18. </document>     
  19.   
  20. </dataConfig>  


3.4.4 第四步:重启tomcat

3.4.5 第五步:点击“execute”按钮导入数据

 

注意:到入数据前会先清空索引库,然后再导入。导入完成需手动刷新或者选择下面自动刷新


 

4     Solrj的使用



4.1     什么是solrj

solrj是访问Solr服务的java客户端,提供索引和搜索的请求方法,SolrJ通常在嵌入在业务系统中,通过SolrJ的API接口操作Solr服务,如下图:


Solrj和图形界面操作的区别就类似于数据库中你使用jdbc和mysql客户端的区别一样。


4.2     需求

使用solrj调用solr服务实现对索引库的增删改查操作。

 

4.3     环境准备

l  Solr:4.10.3

l  Jdk环境:1.7.0_72(solr4.10 不能使用jdk1.7以下

l  Ide环境:eclipse indigo


4.4     工程搭建


4.4.1 第一步:创建java工程

4.4.2 第二步:添加jar

l  Solrj的包


l  Solr服务的依赖包



4.5     代码实现

4.5.1 添加\修改索引

4.5.1.1  步骤

1、 创建HttpSolrServer对象,通过它和Solr服务器建立连接。

2、 创建SolrInputDocument对象,然后通过它来添加域。

3、 通过HttpSolrServer对象将SolrInputDocument添加到索引库。

4、 提交。

4.5.1.2  代码

说明:根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.        @Test  
  2. public void addDocument() throws Exception {  
  3.   
  4.     // 1、 创建HttpSolrServer对象,通过它和Solr服务器建立连接。  
  5.     // 参数:solr服务器的访问地址  
  6.     HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/");  
  7.     // 2、 创建SolrInputDocument对象,然后通过它来添加域。  
  8.     SolrInputDocument document = new SolrInputDocument();  
  9.     // 第一个参数:域的名称,域的名称必须是在schema.xml中定义的  
  10.     // 第二个参数:域的值  
  11.     // 注意:id的域不能少  
  12.     document.addField("id""c0001");  
  13.     document.addField("title_ik""使用solrJ添加的文档");  
  14.     document.addField("content_ik""文档的内容");  
  15.     document.addField("product_name""商品名称");  
  16.     // 3、 通过HttpSolrServer对象将SolrInputDocument添加到索引库。  
  17.     server.add(document);  
  18.     // 4、 提交。  
  19.     server.commit();  
  20. }  


4.5.1.3  查询测试

 

4.5.2 删除索引

4.5.2.1  根据ID删除

4.5.2.1.1代码

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.        @Test  
  2. public void deleteDocument() throws Exception {  
  3.     // 1、 创建HttpSolrServer对象,通过它和Solr服务器建立连接。  
  4.     // 参数:solr服务器的访问地址  
  5.     HttpSolrServer server = new HttpSolrServer(  
  6.             "http://localhost:8080/solr/");  
  7.     // 根据ID删除  
  8.     server.deleteById("c0001");  
  9.     // 提交  
  10.     server.commit();  
  11. }  


4.5.2.1.2查询测试

4.5.2.2  根据条件删除

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Test  
  2.     public void deleteDocumentByQuery() throws Exception {  
  3.         // 1、 创建HttpSolrServer对象,通过它和Solr服务器建立连接。  
  4.         // 参数:solr服务器的访问地址  
  5.         HttpSolrServer server = new HttpSolrServer(  
  6.                 "http://localhost:8080/solr/");  
  7.         // 根据ID删除  
  8.         server.deleteByQuery("id:c0001");  
  9.         // 全部删除  
  10.         // server.deleteByQuery("*:*");  
  11.         // 提交  
  12.         server.commit();  
  13.     }  


4.5.3 查询索引

4.5.3.1  solr的查询语法

1.      q - 查询关键字,必须的,如果查询所有使用*:*。

请求的q是字符串

 

 

2.      fq- (filter query)过虑查询,作用:在q查询符合结果中同时是fq查询符合的,例如::

请求fq是一个数组(多个值)


过滤查询价格从1到20的记录。

也可以在“q”查询条件中使用product_price:[1TO 20],如下:


也可以使用“*”表示无限,例如:

20以上:product_price:[20TO *]

20以下:product_price:[*TO 20]

 

3.      sort - 排序,格式:sort=<fieldname>+<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,设置格式前缀和后缀。

 

 

4.5.3.2  简单查询

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Test  
  2.     public void queryIndex() throws Exception {  
  3.         // 创建HttpSolrServer对象,通过它和Solr服务器建立连接。  
  4.         // 参数:solr服务器的访问地址  
  5.         HttpSolrServer server = new HttpSolrServer(  
  6.                 "http://localhost:8080/solr/");  
  7.   
  8.         // 创建SolrQuery对象  
  9.         SolrQuery query = new SolrQuery();  
  10.         // 设置查询条件,名称“q”是固定的且必须 的  
  11.         query.set("q""id:2");  
  12.   
  13.         // 调用server的查询方法,查询索引库  
  14.         QueryResponse response = server.query(query);  
  15.   
  16.         // 查询结果  
  17.         SolrDocumentList results = response.getResults();  
  18.   
  19.         // 查询结果总数  
  20.         long cnt = results.getNumFound();  
  21.         System.out.println("查询结果总数:" + cnt);  
  22.   
  23.         for (SolrDocument solrDocument : results) {  
  24.             System.out.println(solrDocument.get("id"));  
  25.             System.out.println(solrDocument.get("product_name"));  
  26.             System.out.println(solrDocument.get("product_price"));  
  27.             System.out.println(solrDocument.get("product_catalog_name"));  
  28.             System.out.println(solrDocument.get("product_picture"));  
  29.   
  30.         }  
  31.     }  


4.5.3.3  复杂查询

复杂查询中包括高亮的处理


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Test  
  2.     public void queryIndex2() throws Exception {  
  3.         // 创建HttpSolrServer对象,通过它和Solr服务器建立连接。  
  4.         // 参数:solr服务器的访问地址  
  5.         HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/");  
  6.   
  7.         // 创建SolrQuery对象  
  8.         SolrQuery query = new SolrQuery();  
  9.   
  10.         // 设置查询条件  
  11.         query.setQuery("钻石");  
  12.         // 设置过滤条件  
  13.         query.setFilterQueries("product_catalog_name:幽默杂货");  
  14.         // 设置排序  
  15.         query.setSort("product_price", ORDER.desc);  
  16.         // 设置分页信息  
  17.         query.setStart(0);  
  18.         query.setRows(10);  
  19.   
  20.         // 设置显得的域的列表  
  21.         query.setFields("id""product_name""product_price",  
  22.                 "product_catalog_name""product_picture");  
  23.   
  24.         // 设置默认搜索域  
  25.         query.set("df""product_name");  
  26.   
  27.         // 设置高亮  
  28.         query.setHighlight(true);  
  29.         query.addHighlightField("product_name");  
  30.         query.setHighlightSimplePre("<em>");  
  31.         query.setHighlightSimplePost("</em>");  
  32.   
  33.         // 调用server的查询方法,查询索引库  
  34.         QueryResponse response = server.query(query);  
  35.   
  36.         // 查询结果  
  37.         SolrDocumentList results = response.getResults();  
  38.   
  39.         // 查询结果总数  
  40.         long cnt = results.getNumFound();  
  41.         System.out.println("查询结果总数:" + cnt);  
  42.   
  43.         for (SolrDocument solrDocument : results) {  
  44.             System.out.println(solrDocument.get("id"));  
  45.   
  46.             String productName = (String) solrDocument.get("product_name");  
  47.   
  48.             //获取高亮列表  
  49.             Map<String, Map<String, List<String>>> highlighting = response  
  50.                     .getHighlighting();  
  51.             //获得本文档的高亮信息  
  52.             List<String> list = highlighting.get(solrDocument.get("id")).get(  
  53.                     "product_name");  
  54.             //如果有高亮,则把商品名称赋值为有高亮的那个名称  
  55.             if (list != null) {  
  56.                 productName = list.get(0);  
  57.             }  
  58.   
  59.             System.out.println(productName);  
  60.             System.out.println(solrDocument.get("product_price"));  
  61.             System.out.println(solrDocument.get("product_catalog_name"));  
  62.             System.out.println(solrDocument.get("product_picture"));  
  63.   
  64.         }  
  65.     }  



5     案例



5.1     需求

使用Solr实现电商网站中商品信息搜索功能,可以根据关键字、分类、价格搜索商品信息,也可以根据价格进行排序。

界面如下:

 

5.2     分析

开发人员需要的文档:静态页面(根据UI设计由美工给出)、数据库设计、原型设计

5.2.1 UI分析


5.2.2 架构分析


架构分为:

1、 solr服务器

2、 自己开发的应用(重点)

3、 数据库mysql

 

业务流程


自己开发的应用

1、 Controller

和前端页面进行请求和响应的交互

2、 Service

使用solrj来调用solr的服务进行索引和搜索

Service调用dao进行商品数据的维护时,要同步更新索引库

3、 Dao

对商品数据进行维护和查询

5.3     环境准备

l  Solr:4.10.3

l  Jdk环境:1.7.0_72(solr4.10 不能使用jdk1.7以下

l  Ide环境:eclipse indigo

l  Web服务器(servlet容器):Tomcat 7X

5.4     工程搭建

5.4.1 第一步:创建web工程

5.4.2 第二步:添加jar包

l  Solrj的包

l  Solr服务的日志包

l  spring的包(包含springmvc)

l  Jstl包

l  Commons日志包


5.5     代码实现

5.5.1 Pojo

5.5.1.1  分析

索引查询结果


通过分析得出:

l  需要一个商品的pojo(Product),存放商品信息

l  还需要一个包装pojo(ResultModel),它包括商品列表信息、商品分页信息

5.5.1.2  代码

Product.java

public class Product {

    // 商品编号

    private Stringpid;

    // 商品名称

    private Stringname;

    // 商品分类名称

    private Stringcatalog_name;

    // 价格

    private float price;

    // 商品描述

    private Stringdescription;

    // 图片名称

    private String picture;

}

 

ResultModel.java

public class ResultModel {

    // 商品列表

    private List<Product>productList;

    // 商品总数

    private LongrecordCount;

    // 总页数

    private int pageCount;

    // 当前页

    private int curPage;

 

}

 

5.5.2 Dao

功能:接收service层传递过来的参数,根据参数查询索引库,返回查询结果。

public interface ProductDao {

 

    //查询商品信息,包括分页信息

    public ResultModel queryProduct(SolrQuery query) throws Exception;

}

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class ProductDaoImpl implements ProductDao {  
  2.   
  3.     @Autowired  
  4.     private HttpSolrServer server;  
  5.   
  6.     @Override  
  7.     public ResultModel queryProduct(SolrQuery query) throws Exception {  
  8.         ResultModel result = new ResultModel();  
  9.         // 通过server查询索引库  
  10.         QueryResponse response = server.query(query);  
  11.         // 获得查询结果  
  12.         SolrDocumentList documentList = response.getResults();  
  13.         // 把查询结果总数设置到ResultModel  
  14.         result.setRecordCount(documentList.getNumFound());  
  15.   
  16.         List<Product> productList = new ArrayList<>();  
  17.         Product product = null;  
  18.         // 高亮信息  
  19.         Map<String, Map<String, List<String>>> highlighting = response  
  20.                 .getHighlighting();  
  21.         for (SolrDocument solrDocument : documentList) {  
  22.             product = new Product();  
  23.             product.setPid((String) solrDocument.get("id"));  
  24.   
  25.             String prodName = (String) solrDocument.get("product_name");  
  26.   
  27.             List<String> list = highlighting.get(solrDocument.get("id")).get(  
  28.                     "product_name");  
  29.             if (list != null)  
  30.                 prodName = list.get(0);  
  31.   
  32.             product.setName(prodName);  
  33.             product.setCatalog_name((String) solrDocument  
  34.                     .get("product_catalog_name"));  
  35.             product.setPrice((float) solrDocument.get("product_price"));  
  36.             product.setPicture((String) solrDocument.get("product_picture"));  
  37.   
  38.             productList.add(product);  
  39.         }  
  40.   
  41.         // 把商品列表放到ResultMap中  
  42.         result.setProductList(productList);  
  43.         return result;  
  44.     }  
  45.   
  46. }  


5.5.3 Service

功能:接收action传递过来的参数,根据参数拼装一个查询条件,调用dao层方法,查询商品列表。接收返回的商品列表和商品的总数量,根据每页显示的商品数量计算总页数。

public interface ProductService {

 

    public ResultModelqueryProduct(String queryString, String cataName,

             String price, String sort, Integer curPage) throws Exception;

}

 


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Service  
  2. public class ProductServiceImpl implements ProductService {  
  3.   
  4.     @Autowired  
  5.     private ProductDao dao;  
  6.   
  7.     @Override  
  8.     public ResultModel queryProduct(String queryString, String cataName,  
  9.             String price, String sort, Integer curPage) throws Exception {  
  10.         // 封装SolrQuery  
  11.         SolrQuery query = new SolrQuery();  
  12.         // 设置查询条件  
  13.         if (queryString != null && !"".equals(queryString)) {  
  14.             query.setQuery(queryString);  
  15.         }else{  
  16.             query.setQuery("*:*");  
  17.         }  
  18.         // 设置过滤条件  
  19.         if (cataName != null && !"".equals(cataName)) {  
  20.             query.addFilterQuery("product_catalog_name:" + cataName);  
  21.         }  
  22.         if (price != null && !"".equals(price)) {  
  23.             String[] strings = price.split("-");  
  24.             if (strings.length == 2) {  
  25.                 query.addFilterQuery("product_price:[" + strings[0] + " TO "  
  26.                         + strings[1] + "]");  
  27.             }  
  28.         }  
  29.         // 设置排序(1:降序 0:升序)  
  30.         if ("1".equals(sort)) {  
  31.             query.setSort("product_price", ORDER.desc);  
  32.         } else {  
  33.             query.setSort("product_price", ORDER.asc);  
  34.         }  
  35.         // 设置分页信息  
  36.         if (curPage == null)  
  37.             curPage = 1;  
  38.         query.setStart((curPage - 1) * Constants.rows);  
  39.         query.setRows(Constants.rows);  
  40.   
  41.         // 设置默认搜索域  
  42.         query.set("df""product_name");  
  43.   
  44.         // 设置高亮  
  45.         query.setHighlight(true);  
  46.         query.addHighlightField("product_name");  
  47.         query.setHighlightSimplePre("<font style=\"color:red\">");  
  48.         query.setHighlightSimplePost("</font>");  
  49.   
  50.         ResultModel resultModel = dao.queryProduct(query);  
  51.         resultModel.setCurPage(curPage);  
  52.         return resultModel;  
  53.     }  
  54.   
  55. }  


5.5.4 Controller

5.5.4.1  代码

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Controller  
  2. public class ProductController {  
  3.   
  4.     @Autowired  
  5.     private ProductService service;  
  6.   
  7.     @RequestMapping("/list")  
  8.     public String queryProduct(String queryString, String catalog_name,  
  9.             String price, String sort, Integer page, Model model)  
  10.             throws Exception {  
  11.   
  12.         ResultModel resultModel = service.queryProduct(queryString, catalog_name,  
  13.                 price, sort, page);  
  14.         model.addAttribute("result", resultModel);  
  15.         model.addAttribute("queryString", queryString);  
  16.         model.addAttribute("caltalog_name", catalog_name);  
  17.         model.addAttribute("price", price);  
  18.         model.addAttribute("sort", sort);  
  19.         model.addAttribute("page", page);  
  20.   
  21.         return "product_list";  
  22.     }  
  23. }  


5.5.4.2  配置

5.5.4.2.1Web.xml
[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
  5.     id="WebApp_ID" version="2.5">  
  6.     <display-name>jd0723</display-name>  
  7.     <!-- SpringMVC配置 -->  
  8.     <servlet>  
  9.         <servlet-name>springmvc</servlet-name>  
  10.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  11.         <init-param>  
  12.             <param-name>contextConfigLocation</param-name>  
  13.             <param-value>classpath:springmvc.xml</param-value>  
  14.         </init-param>  
  15.     </servlet>  
  16.     <servlet-mapping>  
  17.         <servlet-name>springmvc</servlet-name>  
  18.         <url-pattern>*.action</url-pattern>  
  19.     </servlet-mapping>  
  20.     <filter>  
  21.         <filter-name>Character Encoding</filter-name>  
  22.         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
  23.         <init-param>  
  24.             <param-name>encoding</param-name>  
  25.             <param-value>UTF-8</param-value>  
  26.         </init-param>  
  27.     </filter>  
  28.     <filter-mapping>  
  29.         <filter-name>Character Encoding</filter-name>  
  30.         <url-pattern>/*</url-pattern>  
  31.     </filter-mapping>  
  32. </web-app>  


5.5.4.2.2Springmvc.xml

在config包下,创建springmvc.xml文件

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"  
  4.     xmlns:context="http://www.springframework.org/schema/context"  
  5.     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans   
  7.         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd   
  8.         http://www.springframework.org/schema/mvc   
  9.         http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd   
  10.         http://www.springframework.org/schema/context   
  11.         http://www.springframework.org/schema/context/spring-context-3.1.xsd   
  12.         http://www.springframework.org/schema/aop   
  13.         http://www.springframework.org/schema/aop/spring-aop-3.1.xsd   
  14.         http://www.springframework.org/schema/tx   
  15.         http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">  
  16.     <!-- 配置扫描包 -->  
  17.     <context:component-scan base-package="cn.itcast" />  
  18.     <!-- 配置注解驱动 -->  
  19.     <mvc:annotation-driven />  
  20.     <!-- jsp视图解析器 -->  
  21.     <bean  
  22.         class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
  23.         <!-- 前缀 -->  
  24.         <property name="prefix" value="/WEB-INF/jsp/"></property>  
  25.         <!-- 后缀 -->  
  26.         <property name="suffix" value=".jsp"></property>  
  27.     </bean>  
  28.     <bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">  
  29.         <constructor-arg value="http://localhost:8080/solr/"></constructor-arg>  
  30.     </bean>  
  31.   
  32. </beans>  


5.5.5 启动Tomcat

访问:http://localhost:8180/jd0723/list.action

0 0
原创粉丝点击