一、简洁

Solr是一个开源的,企业级搜索服务器。她已经是一个成熟的产品,用于强化网络站点的搜索功能,包括内部局域网。

她是用Java语言编写。使用HTTP和XML进行数据传输,Java的掌握对于学习Solr不是必须的。除了能返回搜索

结果外,还有包括高亮搜索关键字,方位导航(已广泛用于电子商务网站),查询关键字拼写校验,自动查询建议

和 “类似”查询 帮助更好定位搜索。

二、Lucene,solr的基础引擎

在相信介绍Solr前,我们先从Apache Lucene开始,Solr的核心基础引擎。Lucene是一个开源的,高效的

文本搜索引擎。Lucene是由Doug Cutting在2000年开发的,并且伴随着强大的在线社区不断进化和成熟。

Lucene不是一个服务器,也不是一个网络爬虫。这一点非常重要,她没有任何配置文件。我们需要编写代码来

存贮和查询在磁盘上的索引。

下面是Lucene的一些主要特征:

  • 通过建立基于文本的反向索引来快速查询文件。
  • 通过丰富的文本分析器(analyzers),将字符串形式的文本信息转换为一系列terms,来联系索引和搜索。
  • 一个查询分析器,还有很多能 支持从简单查询到模糊查询 的查询类型(query types)
  • 一个听上去叫Information Retrieval_r(IR)的得分算法,以产生更多可能的候选结果,有很多灵活的方式来设置得分策略。
  • 在上下文中高亮显示被找到的查询关键字
  • 根据索引内容 来 检查 查询关键字拼写(更多关于查询关键字拼写 可以参考Lucene In Action)

三、Solr,是Lucene的服务器化产物

在对Lucene的了解后,Solr可以理解为Lucene的服务器化产品。但她不是对Lucene的一次简单封装,Solr的大多数特征都与Lucene不同。Solr 和 Lucene 的界限经常是模糊的。以下是Solr的主要特性:

  • 通过HTTP请求来 建立索引和搜索索引
  • 拥有数个缓存 来 加快搜索速度
  • 一个基于web的管理员控制台

运行时做性能统计,包括缓存 命中/错过 率

查询表单 来 搜索索引。

以柱状图形式 展示 频繁被查询的关键字

详细的“得分计算和文本解析”分析。

  • 用XML文件的方式 配置搜索计划和服务器

通过配置XML 来添加和配置 Lucene的文本分析库

引入“搜索字段类型”的概念(这个非常重要,然而在Lucne中没有)。类型用作表示日期和一些特殊的排序问题。

  • 对最终用户和应用成素,disjunction-max 查询处理器比Lucene基础查询器更实用。
  • 查询结果的分类
  • 拼写检查用于寻找搜索关键字 的类似词,优化查询建议
  • “更类似于”插件用以列出 于查询结果类似的 备选结果。
  • Solr支持分布式来应对较大规模的部署。

以上特征都会在下面的章节内详述。

四、Solr 于数据库技术的比较

对于开发人员而言,数据库技术(特别是关系数据库)已经成为一个必须学习的知识。数据库和Lucene的搜索索引并没有显著的不同。假设我们已经非常熟悉数据库知识,现在来描述下她和Lucene有什么不同。(这里来帮助更好了解Solr)

最大的不同是,Lucene可以理解为一个 只有一张简单表格 的数据库,没有任何的关系查询(即JOINS)。这听上去很疯狂,不过记住索引只是为了去支持搜索,而不是去标识一条数据。所以数据库可以去遵守“第三范式”,而索引就不会如此,表格中尽可能多的包含会被搜索到的数据而已。用来补充单表的是,一个域(列)中可以有多值。

其他一些显著的不同:

  • 更新(Update):整个文档可以被删除,然后再添加,但不能被更新。
  • 子字符串搜索与文本搜索:例如“Books”,数据库的Like匹配出“CookBooks”、“MyBooks”。Lucene基于查询分析器的配置,可以查到更多形式的词匹配“Books”,比如book(这里是大小写被忽略),甚至发音相似的词。运用ngram技术,她可以提取部分搜索条件的词干进行匹配。
  • 结果打分:Lucene的强大在于她可以根据结果的匹配程度来打分。例如查询条件中有部分是可选的(OR search),那匹配程度高的文档会得到更多的分。有一些其他因素,可以调整打分的方式。然而,数据库就没有这个功能,只是匹配或不匹配。Lucene也可以在需要的时候对结果进行排序。
  • 延迟提交:Solr的搜索速度通过建立缓存得以优化。当一个完成的文档需要被提交,所有的缓存会重新构建,根据其他一些因素,这可能花费几秒到一分钟。

五、正式开始Solr

Solr是用Java编写的,不过我们不需要对Java非常了解。如果需要扩展Solr的功能,那我们需要了解Java。

我们需要掌握的是命令行操作,包括Dos和Unix。

在正式开始前,我们可能需要安装以下一些包:

  • A Java Development Kit(JDK) v1.5 or later.
  • Apache Ant: Any recent version
  • Subversion or Git for source control of Solr: svn 或 git
  • Any Java EE servlet Engine app-server:Sole 已经自带了Jetty。
  • Solr:http://lucene.apache.org/solr ,现在官方是1.4版本。也可以去取源代码获得最新版本。(经过单元和集成测试,也是非常稳定和可靠的),通过 svn cohttp://svn.apache.org/repos/asf/lucene/solr/trunk/ solr_svn 将最新的源代码下载到本地solr_svn目录下。

Solr 发布包下的目录结构:

  • client::包含特定的编程语言与Solr通信。这里其实只有Ruby的例子。Java的客户端在src/solrj
  • dist:这里包含Solr的Jar包和War包
  • example:这里有Jetty安装所需要的包(Solr自带Jetty),包括一些样本数据和Solr的配置文件。

example/etc:Jetty的配置文件。可以修改监听端口(默认8983)

example/multicore:多核环境下,solr的根目录(后面会具体讨论)

example/solr:默认环境下的solr根目录

example/webapps:Solr的WAR包部署在这里

  • lib:所有Solr依赖的包。一大部分是Lucene,一些Apache常用的工具包,和Stax(XML处理相关)
  • src:各种源码。可以归为以下几个重要目录:

src/java:Solr的源代码,用Java编写。

src/scripts:Unix的bash shell脚本,应用与在大型应用中部署多个Solr服务。

src/solrj:Solr Java的客户端。

src/webapp:Solr web端的管理员用户界面,包括Servlets和JSP。这些其实也都是War中的内容。

注意:要看Java源码的话,src/java下是主要的Solr源码;src/common下是一部分通用类,供server端和solrj客户端;src/test中是测试代码;src/webapp/src下是servlet代码;

六、Solr的根目录

Solr的根目录下包括Solr的配置和运行Solr实例需要的数据。

Sole有一个样例根目录,在example/solr下,我们将会使用这个

另一个更技术层面的,在example/solr下,也是Solr的一个根目录不过是用在多核的环境下,稍后讨论。

让我们来看下根目录下有些什么:

  • bin:如果想自己设置Solr,这里可以放脚本。
  • conf:配置文件。下面的2个文件很重要,这个文件夹下还包括一些其他文件,都是被这2个文件引用,为了一些其他配置,比如文本分析的细节。

conf/schema.xml:这里是索引的概要,包括 域类型(field type)定义和相关分析器链。

conf/sorconfig.xml:这是Solr配置的主文件。

conf/xslt:这个目录薄厚一些XSLT文件,用来把Solr搜索结果(XML)转换为其他形式,例如Atom/RSS。

  • data:包含Lucene的索引数据,Solr自动生成。这些都是二进制数据(binary),我们基本不会去动它,除非需要删除。
  • lib:一些额外的,可选的Java Jar包,Solr会在启动时调用。当你不是通过修改Solr源码 强化Solr的一些功能,可以将包放在这里。

七、Solr如何找到自己的根目录

Solr启动后的第一件事是从根目录加载配置信息。这可以通过好几种方式来指定。

  • Solr先从Java的系统环境变量中搜寻 solr.solr.home这个变量。通常通过命令行设置,如启动Jetty时:java -Dsolr.solr.home = solr/ -jar start .jar ;也可以用JNDI 绑定路径到java:comp/env/solr/home,可以设置web.xml来让app-server维护这个变量(src/web-app/web/WEB-INF)


这里修改了web.xml,需要使用ant dist-war重新打包部署。这里仅仅如此还不够,需要设置JNDI,这里就不深入了。

PS:JNDI需要设置2个环境变量,具体查看EJB相关笔记。

  • 如果根目录没有设置在环境变量或JNDI中,默认地址是 solr/。我们后面会沿用这个地址。(具体产品还是需要配置来设定,比较安全,可以使用绝对或相对路径)

设置完根路径后,在Solr启动中的log会显示:

Aug 7, 2008 4:59:35 PM org.apache.solr.core.Config getInstanceDir
INFO: Solr home defaulted to 'null' (could not find system property or JNDI)
Aug 7, 2008 4:59:35 PM org.apache.solr.core.Config setInstanceDir
INFO: Solr home set to 'solr/'

八、部署和运行Solr

部署就是apach-solr-1.4.war。这里不包含Solr的根目录。

这里我们以自带的Jetty为例子,进入example目录

cd example

java -jar start.jar

看到下面这句日志,即启动完成:

2010-07-09 15:31:06.377::INFO: Started SocketConnector @ 0.0.0.0:8983

在控制台点击Ctrl-C 可以关闭服务器。

0.0.0.0表示她监听来自任务主机的请求,8983是端口号。

此时,可以进入连接:http://localhost:8983/solr,如果启动失败会显示原因,如果成功即可看到管理员入口(http://localhost:8983/solr/admin/)。

九、简单浏览下Solr

顶部灰色部分:

  • 头部信息,当启动多个Solr实例时,可以帮助了解在操作哪个实例。IP地址和端口号都是可见的。
  • example(Admin旁边)是对这个schema的引用,仅仅是标识这个schema。如果你有很多schema,可以用这个标识去区分。
  • 当前工作目录(cwd) ,和Solr的根目录(SolrHome)。

导航栏上的功能:

  • SCHEMA:显示当前的schema的配置文件。(不同浏览器显示可能不同,Firefox会高亮显示语法关键字)
  • CONFIG:显示当前的Solr config文件。
  • ANALYSIS:她用来诊断潜在的 文本分析 的查询/索引问题。这是高级功能,稍后做讨论。
  • SCHEMA BROWSER:这是一个简洁的 反映当前索引中实际存放数据的 视图,稍后做讨论。
  • STATISTICS:这里是 时间和缓存命中率统计。稍后做讨论。
  • INFO:她列出了Solr当前应用组件的版本信息,不是很常用。
  • DISTRIBUTION:这里包含了分布式/复制的状态信息,稍后讨论。
  • PING:可以忽略,她用来在分布式模式下提供健壮性检查。
  • LOGGING:可以在这里设置Solr不同部分的Logging levels。在Jetty下,输出的信息都在控制台。(Solr使用SLF4j)
  • JAVA PROPERTIES:列出了JAVA系统环境变量。
  • THREAD DUMP:这里显示了Java中的线程信息,帮助诊断问题。
  • FULL INTERFACE:一个更多选择的查询表单,可以帮助诊断问题。这个表单也是能力有限的,只能提交一小部分搜索选项给Solr

Assistance 部分包括一些在线的帮助信息。

十、装在示例数据

Solr有一些示例数据和装载脚本,在example/exampledocs下。

进入example/exampledoce下,输入:

java -jar post.jar *.xml (如果在unix环境下,就运行post.sh)

post.jar是一个简单的程序,会遍历所有的参数(这里就是*.xml),然后对本机正运行的Solr(example)服务器的默认配置(http://localhost:8983/solr/update) 发送post请求(HTTP)。这里可以看下post.sh,就可以了解在干什么了。

可以在控制台命令行中看到发送的文件:

SimplePostTool: POSTing files to http://localhost:8983/solr/update..
SimplePostTool: POSTing file hd.xml
SimplePostTool: POSTing file ipod_other.xml
SimplePostTool: POSTing file ipod_video.xml
SimplePostTool: POSTing file mem.xml
SimplePostTool: POSTing file monitor.xml
SimplePostTool: POSTing file monitor2.xml
SimplePostTool: POSTing file mp500.xml
SimplePostTool: POSTing file payload.xml
SimplePostTool: POSTing file sd500.xml
SimplePostTool: POSTing file solr.xml
SimplePostTool: POSTing file utf8-example.xml
SimplePostTool: POSTing file vidcard.xml
SimplePostTool: COMMITting Solr index changes..

最后一行会执行commit操作,保证之前的文档都被保存,并可见。

理论上post.sh 和 post.jar是可以用在产品脚本上的,但这里仅仅用作示例。

这里取其中一个文件monitor.xml 看下:


这个发送给Solr的文件非常简单。这里只用了一些简单的标签,不过都是非常重要的。

<add>标签中可以放置多个<doc>标签(一个doc代表一个document),在大量数据装载时这样做能提高性能。

Solr在每个POST请求中都会收到一个<commit/>标签。更多的一些特性会在之后介绍。

十一、一次简单的搜索。

在管理员界面,让我们运行一次简单的搜索。

在管理员界面,点击查询按钮,或进入FULL INTERFACE再作更详细的查询。

在我们查看XML输出文件之前,先看下URL和参数信息:

http://localhost:8983/solr/select/?q=monitor&version=2.2&start=0&rows=10&indent=on.

然后浏览器中会显示输出的用XML标识的搜索结果,如下:


这只是一个简单的查询结果,可以加入例如高亮显示等查询条件,然后在result标记后会有更多信息。

十二、一些统计信息

进入http://localhost:8983/solr/admin/stats.jsp。

在这里,当我们没有加载任何数据时,numDocs显示0,而现在显示19。

maxDocs的值取决于当你删除一个文档但却没有提交。

可以关注以下的一些handler:

/update,standard。

注意:这些统计信息都是实时的,不在磁盘上做保存。

十三、solrconfig.xml

这里包含很多我们可以研究的参数,现在先让我们看下<requestHandler>下定义的 request handers。


当我们通过POST通知Solr(如索引一个文档)或通过GET搜索,都会有个特定的request hander做处理。

这些handers可以通过URL来注册。之前我们加载文档时,Solr通过以下注册的handler做处理:

<requestHandler name="/update" class="solr.XmlUpdateRequestHandler" />

而当使用搜索时,是使用solr.SearchHandler(上面的XML定义了)

通过URL参数或POST中的参数,都可以调用这些request handler

也可以在solrconfig.xml中通过default,appends,invariants来指定。

这里的一些参数等于是默认的,就像已经放在了URL后面的参数一样。

十四、一些重要的Solr资源

十五、查询参数

fl=*,score&q.op=AND&start=0&rows=16&hl=true&hl.fl=merHeading&hl.snippets=3&hl.simple.pre=<fontcolor=red>&hl.simple.post=</font>&facet=true&facet.field=merCategory&q=+(merHeading:你好+AND+merHeadingWithWord:潘)+merActualendTime:[1239264030468TO1240473630468]&sort=merActualendTimeasc

fl表示索引显示那些field(*表示所有field, score 是solr 的一个匹配热度)
q.op 表示q 中 查询语句的 各条件的逻辑操作 AND(与) OR(或)
start 开始返回条数
rows 返回多少条
hl 是否高亮
hl.fl 高亮field
hl.snippets 不太清楚(反正是设置高亮3就可以了)
hl.simple.pre 高亮前面的格式
hl.simple.post 高亮后面的格式
facet 是否启动统计
facet.field 统计field
q 查询语句(类似SQL) 相关详细的操作还需lucene 的query 语法
sort 排序

十六、删除索引

post "<delete><id>42</id></delete>"




-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

对一个document进行索引时,其中的每个field中的数据都会经历分析(根据上面的一个博客可以知道,分析就是组合分词和过滤),最终将一句话分成单个的单词,去掉句子当中的空白符号,大写转换小写,复数转单数,去掉多余的词,进行同义词代换等等。 



 如:This is a blog! this, is, a 会被去除,最后最剩下blog。当然!这个符号也会被去除的。 



 这个过程是在索引和查询过程中都会进行的,而且通常两者进行的处理的都是一样的,这样做是为了保证建立的索引和查询的正确匹配。 



分析器(Analyzer) 


 分析器是包括两个部分:分词器和过滤器。分词器功能将句子分成单个的词元token,过滤器就是对词元进行过滤。 


 solr自带了一些分词器,如果你需要使用自定义的分词器,那么就需要修改schema.xml文件。 


 schema.xml 文件允许两种方式修改文本被分析的方式,通常只有field类型为 solr.TextField 的field的内容允许定制分析器。 


   方法一:使用任何 org.apache.lucene.analysis.Analyzer的子类进行设定。 


" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer">  
   

 
   
 
1. <fieldType name="text" class="solr.TextField">    
2.      <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>    
3. </fieldType>




   方法二:指定一个TokenizerFactory ,后面跟一系列的TokenFilterFactories(它们将按照所列的顺序发生作用),Factories被用来创建分词器和分词过滤器,它们用于对分词器和分词过滤器的准备配置,这样做的目的是为了避免the overhead of creation via reflection。 

…… …… " quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer">  
   

 
   
 
1. <analyzer type="index">    
2.        <tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" isMaxWordLength="false"/>    
3. ……    
4.    
5.    </analyzer>    
6.    <analyzer type="query">    
7.        <tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" isMaxWordLength="true"/>    
8.    ……    
9.    </analyzer>



 需要说明的一点是,Any Analyzer, TokenizerFactory, or TokenFilterFactory 应该用带包名的全类名进行指定,请确保它们位于Solr的classpath 路径下。对于 org.apache.solr.analysis.* 包下的类,仅仅通过solr.*就可以进行指定。 



  如果你需要使用自己的分词器和过滤器,你就需要自己写一个 factory ,它必须是 BaseTokenizerFactory(分词器) 或BaseTokenFilterFactory(过滤器)的子类。就像下面一样。 

对于IK3.1.5版本已经完全支持了solr的分词,这样就不用自己来编写了,而对于中文的切词的话,ik对solr的支持已经很完美了。

 
   
 
1. public class MyFilterFactory extends BaseTokenFilterFactory {  
2.  public TokenStream create(TokenStream input) {  
3.    return new MyFilter(input);  
4.  }  
5. }




Solr提供了哪些TokenizerFactories? 



1. 



  创建org.apache.lucene.analysis.LetterTokenizer. 


  分词举例: 


  "I can't" ==> "I", "can", "t",字母切词。 



2.  solr.WhitespaceTokenizerFactory



  创建org.apache.lucene.analysis.WhitespaceTokenizer,主要是切除所有空白字符。 



3.  solr.LowerCaseTokenizerFactory



  创建org.apache.lucene.analysis.LowerCaseTokenizer 


  分词举例: 


 "I can't" ==> "i", "can", "t",主要是大写转小写。 



4.  solr.StandardTokenizerFactory



  创建org.apache.lucene.analysis.standard.StandardTokenizer 


  分词举例:  "I.B.M. cat's can't" ==> 


ACRONYM: "I.B.M.", APOSTROPHE:"cat's", APOSTROPHE:"can't" 



  说明:该分词器,会自动地给每个分词添加type,以便接下来的对type敏感的过滤器进行处理,目前仅仅只有StandardFilter对Token的类型是敏感的。 


关键字: 搜索引擎 solr 分词 


5.  solr.HTMLStripWhitespaceTokenizerFactory



从结果中出去HTML标签,将结果交给WhitespaceTokenizer处理。 


例子: 


my <a href="www.foo.bar">link</a>  

my link  

<?xml?><br>hello<!--comment-->  

hello  

hello<script><-- f('<--internal--></script>'); --></script>  

hello  

if a<b then print a;  

if a<b then print a;  

hello <td height=22 nowrap align="left">  

hello  

a<b A Alpha&Omega Ω  

a<b A Alpha&Omega Ω



6.  solr.HTMLStripStandardTokenizerFactory



从结果中出去HTML标签,将结果交给StandardTokenizer处理。 


7. 



说明:按照规则表达式样式对分本进行分词。 


例子:处理对象为,mice; kittens; dogs,他们由分号加上一个或多个的空格分隔。 


" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer">  
   

 
   
 
1. <fieldType name="semicolonDelimited" class="solr.TextField">  
2.  <analyzer>  
3.     <tokenizer class="solr.PatternTokenizerFactory" pattern="; *" />  
4.  </analyzer>  
5. </fieldType>


Solr有哪些TokenFilterFactories? 



1. 



创建:org.apache.lucene.analysis.standard.StandardFilter. 


移除首字母简写中的点和Token后面的’s。仅仅作用于有类的Token,他们是由StandardTokenizer产生的。 


例:StandardTokenizer+ StandardFilter 


"I.B.M. cat's can't" ==> "IBM", "cat", "can't" 


2. 



创建:org.apache.lucene.analysis.LowerCaseFilter. 


3. 



创建:org.apache.solr.analysis.TrimFilter 


去掉Token两端的空白符 


例: 


" Kittens!   ", "Duck" ==> "Kittens!", "Duck". 


4. 



创建:org.apache.lucene.analysis.StopFilter 


去掉如下的通用词,多为虚词。 

"a", "an", "and", "are", "as", "at", "be", "but", "by",  

   "for", "if", "in", "into", "is", "it",  

   "no", "not", "of", "on", "or", "s", "such",  

   "t", "that", "the", "their", "then", "there", "these",  

   "they", "this", "to", "was", "will", "with"

自定义的通用词表的使用可以通过schema.xml文件中的"words"属性来指定,如下。 

" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer">  
   

 
   
 
1. <fieldtype name="teststop" class="solr.TextField">  
2.   <analyzer>  
3.     <tokenizer class="solr.LowerCaseTokenizerFactory"/>  
4.     <filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>  
5.   </analyzer>  
6. </fieldtype>



5.  



创建:org.apache.solr.analysis.KeepWordFilter 


作用与solr.StopFilterFactory相反,保留词的列表也可以通过”word”属性进行指定。 

" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer">  
   

 
   
 
1. <fieldtype name="testkeep" class="solr.TextField">  
2.   <analyzer>  
3.     <filter class="solr.KeepWordFilterFactory" words="keepwords.txt" ignoreCase="true"/>  
4.   </analyzer>  
5. </fieldtype>

6.      


创建:solr.LengthFilter 


过滤掉长度在某个范围之外的词。范围设定方式见下面。 

" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer">  
   

 
   
 
1. <fieldtype name="lengthfilt" class="solr.TextField">  
2.  <analyzer>  
3.    <tokenizer class="solr.WhitespaceTokenizerFactory"/>  
4.    <filter class="solr.LengthFilterFactory" min="2" max="5" />  
5.  </analyzer>  
6. </fieldtype>



7. 



创建:org.apache.lucene.analysis.PorterStemFilter 


采用Porter Stemming Algorithm算法去掉单词的后缀,例如将复数形式变成单数形式,第三人称动词变成第一人称,现在分词变成一般现在时的动词。 


8.  solr.EnglishPorterFilterFactory



创建:solr.EnglishPorterFilter 


关于句子主干的处理,其中的"protected"指定不允许修改的词的文件。 


9.  solr.SnowballPorterFilterFactory



关于不同语言的词干处理 


10.solr.WordDelimiterFilterFactory



关于分隔符的处理。 


11.solr.SynonymFilterFactory



关于同义词的处理。 


12.solr.RemoveDuplicatesTokenFilterFactory



避免重复处理。 

-----------------------------------------------------------------------------------------------------------------------------------


Apache Solr索引富文本(html word pdf)



lucene对索引的更新比solr麻烦,solr只需要调用一个函数UpdateRequest.setAction(AbstractUpdateRequest.ACTION.COMMIT, false, false)就完成了更新,而lucene需要先删除再更新,否则就变成增量索引了

lucene更新索引:http://langhua9527.iteye.com/blog/582347

前面已经简单介绍了solr的安装与使用,下面来看看如何用客户端solrj来建立索引及查询



view plain

solrj要成功运行,需要导入下列包才行

1. importjava.io.IOException;  
2. importjava.util.ArrayList;  
3. importjava.util.Collection;  
4.  
5. importorg.apache.solr.client.solrj.SolrQuery;  
6. importorg.apache.solr.client.solrj.SolrServer;  
7. importorg.apache.solr.client.solrj.SolrServerException;  
8. importorg.apache.solr.client.solrj.impl.CommonsHttpSolrServer;  
9. importorg.apache.solr.client.solrj.request.AbstractUpdateRequest;  
10. importorg.apache.solr.client.solrj.request.UpdateRequest;  
11. importorg.apache.solr.client.solrj.response.QueryResponse;  
12. importorg.apache.solr.common.SolrInputDocument;  
13.  
14. publicclassSolrjTest {  
15.  
16.    publicstaticvoidmain(String[] args) throwsIOException,  
17.            SolrServerException {  
18.  
19.        String urlString = " http://localhost:8080/solr";  
20.        SolrServer server = newCommonsHttpSolrServer(urlString);  
21.  
22.        SolrInputDocument doc1 = newSolrInputDocument();  
23.        doc1.addField("id", 12);  
24.        doc1.addField("content", "my test is easy,测试solr");  
25.        SolrInputDocument doc2 = newSolrInputDocument();  
26.        doc2.addField("id", "solrj简单测试");  
27.        doc2.addField("content", "doc2");  
28.        Collection<SolrInputDocument> docs = newArrayList<SolrInputDocument>();  
29.        docs.add(doc1);  
30.        docs.add( doc2 );  
31.        server.add(docs);  
32.        UpdateRequest req = newUpdateRequest();  
33.        req.setAction(AbstractUpdateRequest.ACTION.COMMIT, false, false);  
34.        req.add(docs);  
35.        req.process(server);  
36.  
37.        SolrQuery query = newSolrQuery();  
38.  
39.        query.setQuery("test");  
40.        query.setHighlight(true).setHighlightSnippets(1);                                                     
41.        query.setParam("hl.fl", "content");  
42.  
43.        QueryResponse ret = server.query(query);  
44.  
45.        System.out.println(ret);  
46.    }  
47. }

From /dist:

apache-solr-solrj-3.1.0.jar

commons-codec-1.4.jar 
commons-httpclient-3.1.jar 
jcl-over-slf4j-1.5.5.jar 
slf4j-api-1.5.5.jar

下面这个包需要去官方下载,因为本人在solr3.1中是没发现这个jar包的,估计是在低版本中有
slf4j-jdk14-1.5.5.jar

solr从1.4版本开始,将apache Tika合并进来,Tika是一个内容抽取的工具集合(a toolkit for text extracting)。它集成了POI, Pdfbox 并且为文本抽取工作提供了一个统一的界面。solr中利用这个工具可以很简单实现对pdf、word等富文本的提取


我的是3.1版,在实现过程中,走了很多弯路,终于还是自己解决了,下面分享一下

view plain

1. packagetest;  
2.  
3. importjava.io.File;  
4. importjava.io.IOException;  
5. importorg.apache.solr.client.solrj.SolrServer;  
6. importorg.apache.solr.client.solrj.SolrServerException;  
7.  
8. importorg.apache.solr.client.solrj.request.AbstractUpdateRequest;  
9. importorg.apache.solr.client.solrj.response.QueryResponse;  
10. importorg.apache.solr.client.solrj.SolrQuery;  
11. importorg.apache.solr.client.solrj.impl.CommonsHttpSolrServer;  
12. importorg.apache.solr.client.solrj.request.ContentStreamUpdateRequest;  
13.  
14.  
15. publicclassSolrExampleTests {  
16.  
17.  publicstaticvoidmain(String[] args) {  
18.    try{  
19.      //Solr cell can also index MS file (2003 version and 2007 version) types. 
20.      String fileName = "D://test//luceneTest//1.pdf";   
21.      //this will be unique Id used by Solr to index the file contents. 
22.      String solrId = "1.pdf";   
23.        
24.      indexFilesSolrCell(fileName, solrId);  
25.        
26.    } catch(Exception ex) {  
27.      System.out.println(ex.toString());  
28.    }  
29.  }  
30.    
31.   
32.  publicstaticvoidindexFilesSolrCell(String fileName, String solrId)   
33.    throwsIOException, SolrServerException {  
34.      
35.    String urlString = "http://localhost:8080/solr";   
36.    SolrServer solr = newCommonsHttpSolrServer(urlString);  
37.      
38.    ContentStreamUpdateRequest up   
39.      = newContentStreamUpdateRequest("/update/extract");  
40.      
41.    up.addFile(newFile(fileName));  
42.      
43.    up.setParam("literal.id", solrId);  
44.    up.setParam("fmap.content", "attr_content");  
45.      
46.    up.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true);  
47.      
48.    solr.request(up);  
49.      
50.    QueryResponse rsp = solr.query(newSolrQuery("*:*"));  
51.      
52.    System.out.println(rsp);  
53.  }  
54. }



刚开始一直在solr.request(up)这一步报错,看tomcat报错是说没有ignored_meta类型,刚开始一直不理解,因为我的配置文件schema.xml中根本没有这种类型,刚开始还以为是版本原因导致,专门去下了solr1.4版,运行果然不报错,后来才想到是因为前面在入门例子中,我修改了配置文件schema.xml,而solrconfig.xml配置文件在/update/extract节点处,有ignored_类型引用,后来我在schema.xml加入ignored_类型后,运行正常


后面研究一下如何用solrj进行查询,并将查询结果展示在web页面上,因为查询结果返回的是xml形式


如果solr是1.3版本或以下,请参考:http://wiki.apache.org/solr/UpdateRichDocuments

参考资料:

1.http://wiki.apache.org/solr/ExtractingRequestHandler
2.http://www.lucidimagination.com/Community/Hear-from-the-Experts/Articles/Content-Extraction-Tika

-----------------------------------------------------------------------------------------------------------


Solr

Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果;

Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。

文档通过Http利用XML 加到一个搜索集合中。查询该集合也是通过http收到一个XML/JSON响应来实现。它的主要特性包括:高效、灵活的缓存功能,垂直搜索功能,高亮显示搜索结果,通过索引复制来提高可用性,提供一套强大Data Schema来定义字段,类型和设置文本分析,提供基于Web的管理界面等。

  

          

     

==================================================================================

Apache Solr:基于Lucene的可扩展集群搜索

关于Solr的未来计划,Seeley提到了更多的可扩展性、对大集群更方便的配置和管理、基于区域和实时的搜索、重构以使用Spring配置插件。

Apache Solr项目,是一款基于Apache Lucene的开源企业搜索服务器,最近发布了1.3版。InfoQ采访了Solr的创建者Yonik Seeley,了解了新版本的更多信息和Solr提供给最终用户的功能。

Seeley首先描述了目标用户:“需要搜索框、分面浏览(导航)或者两者结合的任何人”,Solr的关键特性包括:
基于标准的开放接口——Solr搜索服务器支持通过XML、JSON和HTTP查询和获取结果。
易管理——Solr可以通过HTML页面管理,服务器统计数据以JMX输出,Solr配置通过XML完成。
分面浏览——搜索结果自动分类。
突出显示命中词——匹配的字符自动在搜索结果中高亮显示。
可伸缩性——快速增量更新和快照分发/复制到其他服务器。
灵活的插件体系——新功能能够以插件的形式方便的添加到Solr服务器上。

Seeley同时谈到了该版本中的主要新功能:
分布式搜索——索引现在可以透明的分割成多个部分,单个Solr服务器基于各个配置和模式支持多索引,无须停止Solr服务器就可以改动主要的配置。
扩展了查询功能——包含了一个新的Java客户端(SolrJ)和若干新功能,例如直接配置对于特定查询哪些文档首先命中、近似命中、搜索过期、记录分面时间和拼写检查
增强了数据导入工具——数据库和其他结构化数据源现在都可以导入、映射和转化。
更多可定制扩展点——存在一个新的更新处理器链,允许在查询时修改和重定向文档;一个搜索组件链修改和添加查询结果、用户查询分析器和插件式功能。
性能增强——显著提高了索引速度,二进制响应格式和快速查询删除功能。

详细的更新日志可以这里获得。

Seeley谈到了更多Solr在伸缩性、功能和实用性方面的细节:
Solr已经部署过数以百万计容量的文档,如果借助分布式搜索,Solr应该能够处理数十亿的文档集合。

Solr基于Lucene,具有优秀的全文相关性,可以很方便的提供词组接近性增强、近期文档增强、编辑增强和基于数字值的专有函数的定制评分机制。

AOL正在使用Solr增强它的频道功能:音乐、橄榄球运动、食谱、参考中心、房地产和汽车都使用这项技术。Solr的搜索功能也应用于Netflix、 Zappos、Gamespot、和Internet Archive。还有很多大客户我目前还不能透漏。

关于Solr的未来计划,Seeley提到了更多的可扩展性、对大集群更方便的配置和管理、基于区域和实时的搜索、重构以使用Spring配置插件。Seeley同时提供了一个邮件列表,在那里他详细讨论了Solr未来、特别是2.0版的计划。