solr主要有两个配置solrconfig.xml和schema.xml
schema.xml相当于数据表配置文件,它定义了加入索引的数据的数据类型。主要包括types和fields以及其他一些缺省设置。
注:schema.xml里有一个uniqueKey,的配置,这里将id字段作为索引文档的唯一标识符,非常重要。
1. FieldType(类型)
首先需要在types结点内定义一个FieldType子结点,包括name,class,positionIncrementGap等等一些参数,name就是这个FieldType的名称,class指向org.apache.solr.schema包里面对应的class名称,用来定义这个类型的行为。在FieldType定义的时候最重要的就是定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤。例如:
"text" class="solr.TextField" positionIncrementGap="100">
"index">
class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"
enablePositionIncrements="true"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
……
1.1常规域
● StrField: 这是一个不分词的字符串域,它支持 docValues 域,但当为其添加了docValues 域,则要求只能是单值域且该域必须存在或者该域有默认值
● BoolField : boolean 域,对应 true/false
● TrieIntField, TrieFloatField, TrieLongField, TrieDoubleField 这几个都是默认的数字域, precisionStep 属性一般用于数字范围查询, precisionStep 值越小,则索引时该域的域值分出的 token 个数越多,会增大硬盘上索引的体积,但它会加快数字范围检索的响应速度, positionIncrementGap 属性表示如果当前域是多值域时,多个值之间的间距,单值域,设置此项无意义。
● TrieDateField :显然这是一个日期域类型,不过遗憾的是它支持 1995-12-31T23:59:59Z 这种格式的日期,比较坑爹,为此我自定义了一个 TrieCNDateField 域类型,用于支持国人比较喜欢的 yyyy-MM-dd HH:mm:ss 格式的日期。源码请参见我的上一篇博客。
● BinaryField :经过 base64 编码的字符串域类型,即你需要把 binary 数据进行base64 编码才能被 solr 进行索引。
● RandomSortField :随机排序域类型,当你需要实现伪随机排序时,请使用此域类型。
● TextField :是用的最多的一种域类型,它需要进行分词,所以它一般需要配置分词器。至于具体它如何配置 IK 分词器:一般索引使用最小粒度分词,搜索使用最大分词,
<fieldType class="solr.TextField" name="text_ik">
<analyzer type="index">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false"/>
analyzer>
<analyzer type="query">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true"/>
analyzer>
fieldType>
1.2对应属性
(1)、field type是对field类型的详细描述:
● name:类型的名称,对应field中的type
● class:类型对应的java对象, solr默认提供大概20多种类型
● positionIncrementGap:当field设置multValued为true时,用来分隔多个值之间的间隙大小
● autoGeneratePhraseQueries:有点类似找近义词或者自动纠错的设置,例如可以将 wi fi自动转为 wifi或wi-fi,如果不设置这个属性则需要在查询时强制加上引号,例如 ‘wi fi’
(2)、fieldType 元素还有一些额外的属性也需要注意下,比如sortMissingFirst,sortMissingLast 等:
● sortMissingLast 表示如果域值为 null, 在根据当前域进行排序时,把包含 null 值的document 排在最后一位
● sortMissingFirst :与 sortMissingLast 对应的,不言自明了,你应该懂的
● docValues :表示是否为 docValues 域,一般排序, group,facet 时会用到docValues 域。
在index的analyzer中使用 solr.WhitespaceTokenizerFactory这个分词包,就是空格分词,然后使用 solr.StopFilterFactory,solr.WordDelimiterFilterFactory,solr.LowerCaseFilterFactory,solr.EnglishPorterFilterFactory,solr.RemoveDuplicatesTokenFilterFactory 这几个过滤器。在向索引库中添加text类型的索引的时候,Solr会首先用空格进行分词,然后把分词结果依次使用指定的过滤器进行过滤,最后剩下的结果才会加入到索引库中以备查询。Solr的analysis包并没有带支持中文分词的包
2. Fields(字段)
接下来的工作就是在fields结点内定义具体的字段(类似数据库中的字段),就是filed,filed定义包括name,type(为之前定义过的各种FieldType),indexed(是否被索引),stored(是否被储存),multiValued(是否有多个值)等等。
例:
"id" type="integer" indexed="true" stored="true" required="true" />
"name" type="text" indexed="true" stored="true" />
"summary" type="text" indexed="true" stored="true" />
"author" type="string" indexed="true" stored="true" />
"date" type="date" indexed="false" stored="true" />
"content" type="text" indexed="true" stored="false" />
"keywords" type="keyword_text" indexed="true" stored="false" multiValued="true" />
"all" type="text" indexed="true" stored="false" multiValued="true"/>
2.1 字段的有效属性:
1. name:属性的名称,这里有个特殊的属性“version”是必须添加的。
2. type:字段的数据结构类型,所用到的类型需要在fieldType中设置。
3. default:默认值。
4. indexed:是否创建索引只有index=true 的字段才能做facet.field的字段,同时只有index=true该字段才能当做搜索的内容,当然store=true或者false没关系,将不需要被用于搜索的,而只是作为结果返回的field的indexed设置为false
5. stored:是否存储原始数据(如果不需要存储相应字段值,尽量设为false),表示是否需要把域值存储到硬盘上,方便你后续查询时能再次提取出来原样显示给用户
6. docValues:表示此域是否需要添加一个 docValues 域,这对 facet 查询, group 分组,排序, function 查询有好处,尽管这个属性不是必须的,但他能加快索引数据加载,对 NRT 近实时搜索比较友好,且更节省内存,但它也有一些限制,比如当前docValues 域只支持strField,UUIDField,Trie*Field 等域,且要求域的域值是单值不能是多值域
8. multValued:是否有多个值,比如说一个用户的所有好友id。(对可能存在多值的字段尽量设置为true,避免建索引时抛出错误)
9. omitNorms:此属性若设置为 true ,即表示将忽略域值的长度标准化,忽略在索引过程中对当前域的权重设置,且会节省内存。只有全文本域或者你需要在索引创建过程中设置域的权重时才需要把这个值设false, 对于基本数据类型且不分词的域如intFeild,longField,Stre, 否则默认就是 false.
10. required:添加文档时,该字段必须存在,类似mysql的not null
11. termVectors: 设置为 true 即表示需要为该 field 存储项向量信息,当你需要MoreLikeThis 功能时,则需要将此属性值设为 true ,这样会带来一些性能提升。
12. termPositions: 是否存储 Term 的起始位置信息,这会增大索引的体积,但高亮功能需要依赖此项设置,否则无法高亮
13. termOffsets: 表示是否存储索引的位置偏移量,高亮功能需要此项配置,当你使用SpanQuery 时,此项配置会影响匹配的结果集
field的定义相当重要,有几个技巧需注意一下,对可能存在多值得字段尽量设置 multiValued属性为true,避免建索引是抛出错误;如果不需要存储相应字段值,尽量将stored属性设为false。
3. copyField(复制字段)
建议建立了一个拷贝字段,将所有的全文字段复制到一个字段中,以便进行统一的检索:
"all" type="text" indexed="true" stored="false" multiValued="true"/>
并在拷贝字段结点处完成拷贝设置:
source="name" dest="all"/>
source="summary" dest="all"/>
注:“拷贝字段”就是查询的时候不用再输入:userName:张三 and userProfile:张三的个人简介。直接可以输入”张三”就可以将“名字”含“张三”或者“简介”中含“张三”的又或者“名字”和“简介”都含有“张三”的查询出来。他将需要查询的内容放在了一个字段中,并且默认查询该字段设为该字段就行了。
4. dynamicField(动态字段)
除此之外,还可以定义动态字段,所谓动态字段就是不用指定具体的名称,只要定义字段名称的规则,例如定义一个 dynamicField,name 为*_i,定义它的type为text,那么在使用这个字段的时候,任何以_i结尾的字段都被认为是符合这个定义的,例如:name_i,gender_i,school_i等。
schema.xml配置文件大体上就是这样。
二 solrConfig.xml
solrconfig.xml配置文件主要定义了SOLR的一些处理规则,包括索引数据的存放位置,更新,删除,查询的一些规则配置。
可以在tomcat的安装路径下找到这个文件C:\Program Files\Apache Software Foundation\Tomcat 8.0\solr\collection1\conf
1.datadir节点
${solr.data.dir:d:/Server/Solr/data}//定义了索引数据和日志文件的存放
位置。solr 创建的索引会存放在 data\index 目录下,默认 dataDir 是相对于当前 core 目录 ( 如果 solr_home 下存在 core 的话 ) ,如果 solr_home 下不存在 core 的话,那 dataDir 默认就是相对于 solr_home 啦,不过一般 dataDir 都在 core.properties 下配置。
2.luceneMatchVersion
<luceneMatchVersion>4.8luceneMatchVersion> //表示solr底层使用的是lucene4.8
```
dir="../../../contrib/extraction/lib"regex=".*\.jar"/>
//表示solr引用包的位置,当dir对应的目录不存在时候,会忽略此属性。这里的 dir 表示一个 jar 包目录路径,该目录路径是相对于你当前 core 根目录的; regex 表示一个正则表达式,用来过滤文件名的,符合正则表达式的 jar 文件将会被加载
4.directoryFactory
索引存储方案,共有以下存储方案
1、solr.StandardDirectoryFactory,这是一个基于文件系统存储目录的工厂,它会试图选择最好的实现基于你当前的操作系统和Java虚拟机版本。
2、solr.SimpleFSDirectoryFactory,适用于小型应用程序,不支持大数据和多线程。
3、solr.NIOFSDirectoryFactory,适用于多线程环境,但是不适用在windows平台(很慢),是因为JVM还存在bug。
4、solr.MMapDirectoryFactory,这个是solr3.1到4.0版本在linux64位系统下默认的实现。它是通过使用虚拟内存和内核特性调用mmap去访问存储在磁盘中的索引文件。它允许lucene或solr直接访问I/O缓存。如果不需要近实时搜索功能,使用此工厂是个不错的方案。
5、solr.NRTCachingDirectoryFactory,此工厂设计目的是存储部分索引在内存中,从而加快了近实时搜索的速度。
6、solr.RAMDirectoryFactory,这是一个内存存储方案,不能持久化存储,在系统重启或服务器crash时数据会丢失。且不支持索引复制
<directoryFactory class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}" name="DirectoryFactory">
<str name="solr.hdfs.home">${solr.hdfs.home:}str>
<str name="solr.hdfs.confdir">${solr.hdfs.confdir:}str>
<str name="solr.hdfs.blockcache.enabled">${solr.hdfs.blockcache.enabled:true}str>
<str name="solr.hdfs.blockcache.global">${solr.hdfs.blockcache.global:true}str>
directoryFactory>
<codecFactory class="solr.SchemaCodecFactory"/>
<schemaFactory class="ClassicIndexSchemaFactory"/>
6.indexconfig节点
用于设置索引的低级别的属性
<filter class="solr.LimitTokenCountFilterFactory" maxTokenCount="10000"/>
<writeLockTimeout>1000writeLockTimeout>
<maxIndexingThreads>8maxIndexingThreads>
<useCompoundFile>falseuseCompoundFile>
<ramBufferSizeMB>100ramBufferSizeMB>
<maxBufferedDocs>1000maxBufferedDocs>
<mergePolicy class="org.apache.lucene.index.TieredMergePolicy">
<int name="maxMergeAtOnce">10int>
<int name="segmentsPerTier">10int>
mergePolicy>
<mergeFactor>10mergeFactor>
<mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>
<lockType>${solr.lock.type:native}lockType>
<unlockOnStartup>falseunlockOnStartup>
<termIndexInterval>128termIndexInterval>
<reopenReaders>truereopenReaders>
<deletionPolicy class="solr.SolrDeletionPolicy">
<str name="maxCommitsToKeep">1str>
<str name="maxOptimizedCommitsToKeep">0str>
<str name="maxCommitAge">30MINUTESstr> OR <str name="maxCommitAge">1DAYstr><br>
<infoStream file="INFOSTREAM.txt">falseinfoStream>
updateHandler节点
定义更新处理器,
<updateLog>
<str name="dir">${solr.ulog.dir:}str>
updateLog>
设置索引库更新日志,默认路径为solr home下面的data/tlog。随着索引库的频繁更新,tlog文件会越来越大,所以建议提交索引时采用硬提交方式,即批量提交。
<autoCommit>
<maxTime>15000maxTime>
<maxDocs>10000maxDocs>
<openSearcher>falseopenSearcher>
autoCommit>
autoCommit自动硬提交方式:
maxTime:设置多长时间提交一次,
maxDocs:设置达到多少文档提交一次
openSearcher:文档提交后是否开启新的searcher,如果false,文档只是提交到index索引库,搜索结果中搜不到此次提交的文档;如果true,既提交到index索引库,也能在搜索结果中搜到此次提交的内容。
autoSoftCommit软提交:把内存文件fsync到磁盘,但不创建index descriptor。也就是说原索引和现在的索引还互不感知,所以如果jvm崩溃,那这部分索引就没了。可以重新打开searcher,使得新的索引可以被查找到。
<updateHandler class="solr.DirectUpdateHandler2">
<updateLog>
<str name="dir">${solr.ulog.dir:}str>
updateLog>
<autoCommit>
<maxTime>15000maxTime>
<openSearcher>falseopenSearcher>
autoCommit>
updateHandler>
8.Query查询节点
<maxBooleanClauses>1024maxBooleanClauses>
设置boolean 查询中,最大条件数。在范围搜索或者前缀搜索时,会产生大量的 boolean 条件,
如果条件数达到这个数值时,将抛出异常,限制这个条件数,可以防止条件过多查询等待时间过长。
缓存方法
<filterCache class="solr.FastLRUCache" size="512" initialSize="512" autowarmCount="0"/>
<queryResultCache class="solr.LRUCache" size="512" initialSize="512" autowarmCount="0"/>
<documentCache class="solr.LRUCache" size="512" initialSize="512" autowarmCount="0"/>
<queryResultMaxDocsCached>200queryResultMaxDocsCached> //查询结果文档的最大缓存数
<maxWarmingSearchers>2maxWarmingSearchers> //该参数用于设置最大的 searcher 数量,这些 searcher 实现预热好的,随时可以调用。如果超过这个数量,将会报错。在一个只读的索引库中,2个预热的 searcher 是相对合理的,如果是读写的索引库中,根据内存和cpu的大小可以给一个相对大一点的值。
<enableLazyFieldLoading>trueenableLazyFieldLoading> //某些字段延时加载,以提高性能,例如内容较多的压缩文件
<queryResultWindowSize>50queryResultWindowSize> //Result Window Size 优化queryResultCache结果cache
1)size:cache中可保存的最大的项数,默认是1024
2)initialSize:cache初始化时的大小,默认是1024。
3)autowarmCount:当切换SolrIndexSearcher时,可以对新生成的SolrIndexSearcher做autowarm(预热)处理。autowarmCount表示从旧的SolrIndexSearcher中取多少项来在新的SolrIndexSearcher中被重新生成,如何重新生成由CacheRegenerator实现。在当前的1.4版本的Solr中,这个autowarmCount只能取预热的项数,将来的4.0版本可以指定为已有cache项数的百分比,以便能更好的平衡autowarm的开销及效果。如果不指定该参数,则表示不做autowarm处理。
实现上,LRUCache直接使用LinkedHashMap来缓存数据,由initialSize来限定cache的大小,淘汰策略也是使用LinkedHashMap的内置的LRU方式,读写操作都是对map的全局锁,所以并发性效果方面稍差。
9.Request Dispatcher请求转发器
<requestDispatcher handleSelect="false" >
<requestParsers enableRemoteStreaming="true"
multipartUploadLimitInKB="2048000"
formdataUploadLimitInKB="2048"/>
<httpCaching never304="true" />
requestDispatcher>
10.requestHandler请求处理器
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicitstr>
<int name="rows">10int>
<str name="df">textstr>
lst>
<lst name="appends">
<str name="fq">inStock:truestr>
lst>
<lst name="invariants">
<str name="facet.field">catstr>
<str name="facet.field">manu_exactstr>
<str name="facet.query">price:[* TO 500]str>
<str name="facet.query">price:[500 TO *]str>
lst>
requestHandler>