Solr服务器采用java5开发的,是基于Lucene全文搜索的。要想搭建Solr,首先进行java环境的配置,安装对应的jdk以及tomcat,在此就不多讲。
以下是在jdk1.7和tomcat1.7的环境下搭建最新版本的solr4.10.3。
具体步骤如下:
1.到官网http://lucene.apache.org/solr/mirrors-solr-latest-redir.html下载.
2.建目录/webapps/mysolr/solr
3.解压压缩包solr-4.10.3,找到example下的webapps中的solr.war包,并将其解压。
4.将解压完的war包(solr文件夹)拷贝到第2步建的目录:/webapps/mysolr下
5.拷贝两个地方的jar包到/webapps/mysolr/solr/WEB-INF/lib下
(1)example下lib包的所有jar包
(2)example下lib包下的ext包中的所有jar包
6.拷贝example/resource下的log4j.properties文件到/webapps/mysolr/solr/classpath 下
7.solrhome的配置:
先创建一个solrhome目录:/webapps/mysolr/solrhome,然后将example/solr下的所有文件拷贝到/webapps/mysolr/solrhome下
然后修改配置文件/webapps/mysolr/solr/WEB-INF/web.xml,将solr/home的注解放开并配置如下:
<env-entry>
<env-entry-name>solr/homeenv-entry-name>
<env-entry-value>/webapps/mysolr/solrhomeenv-entry-value>
<env-entry-type>java.lang.Stringenv-entry-type>
env-entry>
8.把/webapps/mysolr/solr部署到tomcat下,并启动tomcat。
以上就完成了solr环境的基本搭建,访问http://loclhost:8080/solr 可看到如下界面:
Solr3.6.1 在Tomcat6下的环境搭建 http://www.cnblogs.com/chinway/p/6187260.html
基于Tomcat的Solr3.5集群部署 http://www.cnblogs.com/chinway/p/6187271.html
在Linux上使用Nginx为Solr集群做负载均衡 http://www.cnblogs.com/chinway/p/6187292.html
Linux下安装使用Solr http://www.cnblogs.com/chinway/p/6187322.html
Solr实现Low Level查询解析(QParser) http://www.cnblogs.com/chinway/p/6187332.html
Solr 4.0 部署实例教程 http://www.cnblogs.com/chinway/p/6187382.html
schema.xml位于solr/conf/目录下,类似于数据表配置文件,
定义了加入索引的数据的数据类型,主要包括type、fields和其他的一些缺省设置。
1、先来看下type节点,这里面定义FieldType子节点,包括name,class,positionIncrementGap等一些参数。
1 < schema name = "example" version = "1.2" >
2 < types >
3 < fieldType name = "string" class = "solr.StrField" sortMissingLast = "true" omitNorms = "true" />
4 < fieldType name = "boolean" class = "solr.BoolField" sortMissingLast = "true" omitNorms = "true" />
5 < fieldtype name = "binary" class = "solr.BinaryField" />
6 < fieldType name = "int" class = "solr.TrieIntField" precisionStep = "0" omitNorms = "true"
7 positionIncrementGap = "0" />
8 < fieldType name = "float" class = "solr.TrieFloatField" precisionStep = "0" omitNorms = "true"
9 positionIncrementGap = "0" />
10 < fieldType name = "long" class = "solr.TrieLongField" precisionStep = "0" omitNorms = "true"
11 positionIncrementGap = "0" />
12 < fieldType name = "double" class = "solr.TrieDoubleField" precisionStep = "0" omitNorms = "true"
13 positionIncrementGap = "0" />
14 ...
15 types >
16 ...
17 schema >
必要的时候fieldType还需要自己定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤,如下:
1 < fieldType name = "text_ws" class = "solr.TextField" positionIncrementGap = "100" >
2 < analyzer >
3 < tokenizer class = "solr.WhitespaceTokenizerFactory" />
4 analyzer >
5 fieldType >
6 < fieldType name = "text" class = "solr.TextField" positionIncrementGap = "100" >
7 < analyzer type = "index" >
8
12 < tokenizer class = "solr.WhitespaceTokenizerFactory" />
13
17
21 < filter class = "solr.StopFilterFactory"
22 ignoreCase = "true"
23 words = "stopwords.txt"
24 enablePositionIncrements = "true"
25 />
26 < filter class = "solr.WordDelimiterFilterFactory" generateWordParts = "1"
27 generateNumberParts = "1" catenateWords = "1" catenateNumbers = "1"
28 catenateAll = "0" splitOnCaseChange = "1" />
29 < filter class = "solr.LowerCaseFilterFactory" />
30 < filter class = "solr.SnowballPorterFilterFactory" language = "English"
31 protected = "protwords.txt" />
32 analyzer >
33 < analyzer type = "query" >
34 < tokenizer class = "solr.WhitespaceTokenizerFactory" />
35 < filter class = "solr.SynonymFilterFactory" synonyms = "synonyms.txt" ignoreCase = "true"
36 expand = "true" />
37 < filter class = "solr.StopFilterFactory"
38 ignoreCase = "true"
39 words = "stopwords.txt"
40 enablePositionIncrements = "true"
41 />
42 < filter class = "solr.WordDelimiterFilterFactory" generateWordParts = "1"
43 generateNumberParts = "1" catenateWords = "0" catenateNumbers = "0"
44 catenateAll = "0" splitOnCaseChange = "1" />
45 < filter class = "solr.LowerCaseFilterFactory" />
46 < filter class = "solr.SnowballPorterFilterFactory" language = "English"
47 protected = "protwords.txt" />
48 analyzer >
49 fieldType >
2、再来看下fields节点内定义具体的字段(类似数据库的字段),含有以下属性:
1 < fields >
2 < field name = "id" type = "integer" indexed = "true" stored = "true" required = "true" />
3 < field name = "name" type = "text" indexed = "true" stored = "true" />
4 < field name = "summary" type = "text" indexed = "true" stored = "true" />
5 < field name = "author" type = "string" indexed = "true" stored = "true" />
6 < field name = "date" type = "date" indexed = "false" stored = "true" />
7 < field name = "content" type = "text" indexed = "true" stored = "false" />
8 < field name = "keywords" type = "keyword_text" indexed = "true" stored = "false" multiValued = "true" />
9
10 < field name = "all" type = "text" indexed = "true" stored = "false" multiValued = "true" />
11 fields >
3、建议建立一个拷贝字段,将所有的 全文本 字段复制到一个字段中,以便进行统一的检索:
以下是拷贝设置:
1 < copyField source = "name" dest = "all" />
2 < copyField source = "summary" dest = "all" />
4、动态字段,没有具体名称的字段,用dynamicField字段
如:name为*_i,定义它的type为int,那么在使用这个字段的时候,任务以_i结果的字段都被认为符合这个定义。如name_i, school_i
1 < dynamicField name = "*_i" type = "int" indexed = "true" stored = "true" />
2 < dynamicField name = "*_s" type = "string" indexed = "true" stored = "true" />
3 < dynamicField name = "*_l" type = "long" indexed = "true" stored = "true" />
4 < dynamicField name = "*_t" type = "text" indexed = "true" stored = "true" />
5 < dynamicField name = "*_b" type = "boolean" indexed = "true" stored = "true" />
6 < dynamicField name = "*_f" type = "float" indexed = "true" stored = "true" />
7 < dynamicField name = "*_d" type = "double" indexed = "true" stored = "true" />
8 < dynamicField name = "*_dt" type = "date" indexed = "true" stored = "true" />
schema.xml文档注释中的信息:
1、为了改进性能,可以采取以下几种措施:
2、
3、filedType
1 < fieldType name =" string " class =" solr.StrField " sortMissingLast =" true " omitNorms =" true " />
可选的属性:
StrField类型不被分析,而是被逐字地索引/存储。
StrField和TextField都有一个可选的属性“compressThreshold”,保证压缩到不小于一个大小(单位:char)
1 < fieldType name =" text " class =" solr.TextField " positionIncrementGap =" 100 " >
solr.TextField 允许用户通过分析器来定制索引和查询,分析器包括一个分词器(tokenizer)和多个过滤器(filter)
name: 字段类型名
class: java类名
indexed: 缺省true。 说明这个数据应被搜索和排序,如果数据没有indexed,则stored应是true。
stored: 缺省true。说明这个字段被包含在搜索结果中是合适的。如果数据没有stored,则indexed应是true。
sortMissingLast: 指没有该指定字段数据的document排在有该指定字段数据的document的后面
sortMissingFirst: 指没有该指定字段数据的document排在有该指定字段数据的document的前面
omitNorms: 字段的长度不影响得分和在索引时不做boost时,设置它为true。一般文本字段不设置为true。
termVectors: 如果字段被用来做more like this 和highlight的特性时应设置为true。
compressed: 字段是压缩的。这可能导致索引和搜索变慢,但会减少存储空间,只有StrField和TextField是可以压缩,这通常适合字段的长度超过200个字符。
multiValued: 字段多于一个值的时候,可设置为true。
positionIncrementGap: 和multiValued
一起使用,设置多个值之间的虚拟空白的数量
1 < tokenizer class =" solr.WhitespaceTokenizerFactory " />
空格分词,精确匹配。
1 < filter class =" solr.WordDelimiterFilterFactory " generateWordParts =" 1 " generateNumberParts =" 1 " catenateWords =" 1 " catenateNumbers =" 1 " catenateAll =" 0 " splitOnCaseChange =" 1 " />
在分词和匹配时,考虑 "-"连字符,字母数字的界限,非字母数字字符,这样 "wifi"或"wi fi"都能匹配"Wi-Fi"。
1 < filter class =" solr.SynonymFilterFactory " synonyms =" synonyms.txt " ignoreCase =" true " expand =" true " />
同义词
1 < filter class =" solr.StopFilterFactory " ignoreCase =" true " words =" stopwords.txt " enablePositionIncrements =" true " />
在禁用字(stopword)删除后,在短语间增加间隔
stopword:即在建立索引过程中(建立索引和搜索)被忽略的词,比如is this等常用词。在conf/stopwords.txt维护。
4、fields
1 < field name =" id " type =" string " indexed =" true " stored =" true " required =" true " />
包罗万象(有点夸张)的field,包含所有可搜索的text fields,通过copyField实现。
在添加索引时,将所有被拷贝field(如cat)中的数据拷贝到text field中
作用:
如果一个field的名字没有匹配到,那么就会用动态field试图匹配定义的各种模式。
1 < dynamicField name =" * " type =" ignored " multiValued=" true " />
如果通过上面的匹配都没找到,可以定义这个,然后定义个type,当String处理。(一般不会发生)
但若不定义,找不到匹配会报错。
5、其他一些标签
1 < uniqueKey > id uniqueKey >
文档的唯一标识, 必须填写这个field(除非该field被标记required="false"),否则solr建立索引报错。
< defaultSearchField > text defaultSearchField >
如果搜索参数中没有指定具体的field,那么这是默认的域。
1 < solrQueryParser defaultOperator =" OR " />
配置搜索参数短语间的逻辑,可以是"AND|OR"。
Solr3.6.1 在Tomcat6下的环境搭建 http://www.cnblogs.com/chinway/p/6187260.html
基于Tomcat的Solr3.5集群部署 http://www.cnblogs.com/chinway/p/6187271.html
在Linux上使用Nginx为Solr集群做负载均衡 http://www.cnblogs.com/chinway/p/6187292.html
Linux下安装使用Solr http://www.cnblogs.com/chinway/p/6187322.html
Solr实现Low Level查询解析(QParser) http://www.cnblogs.com/chinway/p/6187332.html
Solr 4.0 部署实例教程 http://www.cnblogs.com/chinway/p/6187382.html
新华字典,我们都使用过,如叫你翻开第38页,找到“坑爹”所在的位置,此时你会怎么查呢?毫无疑问,你的眼睛会从38页的第一个字开始从头至尾地扫描,直到找到“坑爹”二字为止。这种搜索方法叫做顺序扫描法。对于少量的数据,使用顺序扫描是够用的。但是妈妈叫你查出坑爹的“坑”字在哪一页时,你要是从第一页的第一个字逐个的扫描下去,那你真的是被坑了。此时你就需要用到索引。索引记录了“坑”字在哪一页,你只需在索引中找到“坑”字,然后找到对应的页码,答案就出来了。因为在索引中查找“坑”字是非常快的,因为你知道它的偏旁,因此也就可迅速定位到这个字。
那么新华字典的目录(索引表)是怎么编写而成的呢?首先对于新华字典这本书来说,除去目录后,这本书就是一堆没有结构的数据集。但是聪明的人类善于思考总结,发现每个字都会对应到一个页码,比如“坑”字就在第38页,“爹”字在第90页。于是他们就从中提取这些信息,构造成一个有结构的数据。类似数据库中的表结构:
word page_no
---------------
坑 38
爹 90
... ...
这样就形成了一个完整的目录(索引库),查找的时候就非常方便了。对于全文检索也是类似的原理,它可以归结为两个过程:1.索引创建(Indexing)2. 搜索索引(Search)。那么索引到底是如何创建的呢?索引里面存放的又是什么东西呢?搜索的的时候又是如何去查找索引的呢?带着这一系列问题继续往下看。
Solr/Lucene采用的是一种反向索引,所谓反向索引:就是从关键字到文档的映射过程,保存这种映射这种信息的索引称为反向索引
字段串列表和文档编号链表两者构成了一个字典。现在想搜索”lucene”,那么索引直接告诉我们,包含有”lucene”的文档有:2,3,10,35,92,而无需在整个文档库中逐个查找。如果是想搜既包含”lucene”又包含”solr”的文档,那么与之对应的两个倒排表去交集即可获得:3、10、35、92。
假设有如下两个原始文档:
文档一:Students should be allowed to go out with their friends, but not allowed to drink beer.
文档二:My friend Jerry went to school to see his students but found them drunk which is not allowed.
创建过程大概分为如下步骤:
一:把原始文档交给分词组件(Tokenizer)
分词组件(Tokenizer)会做以下几件事情(这个过程称为:Tokenize),处理得到的结果是词汇单元(Token)
"Students","allowed","go","their","friends","allowed","drink","beer","My","friend","Jerry","went","school","see","his","students","found","them","drunk","allowed"
二:词汇单元(Token)传给语言处理组件(Linguistic Processor)
语言处理组件(linguistic processor)主要是对得到的词元(Token)做一些语言相关的处理。对于英语,语言处理组件(Linguistic Processor)一般做以下几点:
语言处理组件(linguistic processor)处理得到的结果称为词(Term),例子中经过语言处理后得到的词(Term)如下:
"student","allow","go","their","friend","allow","drink","beer","my","friend","jerry","go","school","see","his","student","find","them","drink","allow"。
经过语言处理后,搜索drive时drove也能被搜索出来。Stemming 和 lemmatization的异同:
三:得到的词(Term)传递给索引组件(Indexer)
Term Document ID
student 1
allow 1
go 1
their 1
friend 1
allow 1
drink 1
beer 1
my 2
friend 2
jerry 2
go 2
school 2
see 2
his 2
student 2
find 2
them 2
drink 2
allow 2
Term Document ID
allow 1
allow 1
allow 2
beer 1
drink 1
drink 2
find 2
friend 1
friend 2
go 1
go 2
his 2
jerry 2
my 2
school 2
see 2
student 1
student 2
their 1
them 2
对词(Term) “allow”来讲,总共有两篇文档包含此词(Term),词(Term)后面的文档链表总共有两个,第一个表示包含”allow”的第一篇文档,即1号文档,此文档中,”allow”出现了2次,第二个表示包含”allow”的第二个文档,是2号文档,此文档中,”allow”出现了1次
至此索引创建完成,搜索”drive”时,”driving”,”drove”,”driven”也能够被搜到。因为在索引中,”driving”,”drove”,”driven”都会经过语言处理而变成”drive”,在搜索时,如果您输入”driving”,输入的查询语句同样经过分词组件和语言处理组件处理的步骤,变为查询”drive”,从而可以搜索到想要的文档。
搜索”microsoft job”,用户的目的是希望在微软找一份工作,如果搜出来的结果是:”Microsoft does a good job at software industry…”,这就与用户的期望偏离太远了。如何进行合理有效的搜索,搜索出用户最想要得结果呢?搜索主要有如下步骤:
一:对查询内容进行词法分析、语法分析、语言处理
二:搜索索引,得到符合语法树的文档集合
三:根据查询语句与文档的相关性,对结果进行排序
我们把查询语句也看作是一个文档,对文档与文档之间的相关性(relevance)进行打分(scoring),分数高比较越相关,排名就越靠前。当然还可以人工影响打分,比如百度搜索,就不一定完全按照相关性来排名的。
如何评判文档之间的相关性?一个文档由多个(或者一个)词(Term)组成,比如:”solr”, “toturial”,不同的词可能重要性不一样,比如solr就比toturial重要,如果一个文档出现了10次toturial,但只出现了一次solr,而另一文档solr出现了4次,toturial出现一次,那么后者很有可能就是我们想要的搜的结果。这就引申出权重(Term weight)的概念。
权重表示该词在文档中的重要程度,越重要的词当然权重越高,因此在计算文档相关性时影响力就更大。通过词之间的权重得到文档相关性的过程叫做空间向量模型算法(Vector Space Model)
影响一个词在文档中的重要性主要有两个方面:
文档中词的权重看作一个向量
Document = {term1, term2, …… ,term N}
Document Vector = {weight1, weight2, …… ,weight N}
把欲要查询的语句看作一个简单的文档,也用向量表示:
Query = {term1, term 2, …… , term N}
Query Vector = {weight1, weight2, …… , weight N}
把搜索出的文档向量及查询向量放入N维度的空间中,每个词表示一维:
夹角越小,表示越相似,相关性越大
Solr3.6.1 在Tomcat6下的环境搭建 http://www.cnblogs.com/chinway/p/6187260.html
基于Tomcat的Solr3.5集群部署 http://www.cnblogs.com/chinway/p/6187271.html
在Linux上使用Nginx为Solr集群做负载均衡 http://www.cnblogs.com/chinway/p/6187292.html
Linux下安装使用Solr http://www.cnblogs.com/chinway/p/6187322.html
Solr实现Low Level查询解析(QParser) http://www.cnblogs.com/chinway/p/6187332.html
Solr 4.0 部署实例教程 http://www.cnblogs.com/chinway/p/6187382.html