一、字段配置(schema)
schema.xml位于solr/conf/目录下,类似于数据表配置文件,
定义了加入索引的数据的数据类型,主要包括type、fields和其他的一些缺省设置。
1、先来看下type节点,这里面定义FieldType子节点,包括name,class,positionIncrementGap等一些参数。
- <schemaname="example"version="1.2">
- <types>
- <fieldTypename="string"class="solr.StrField"sortMissingLast="true"omitNorms="true"/>
- <fieldTypename="boolean"class="solr.BoolField"sortMissingLast="true"omitNorms="true"/>
- <fieldtypename="binary"class="solr.BinaryField"/>
- <fieldTypename="int"class="solr.TrieIntField"precisionStep="0"omitNorms="true"
- positionIncrementGap="0"/>
- <fieldTypename="float"class="solr.TrieFloatField"precisionStep="0"omitNorms="true"
- positionIncrementGap="0"/>
- <fieldTypename="long"class="solr.TrieLongField"precisionStep="0"omitNorms="true"
- positionIncrementGap="0"/>
- <fieldTypename="double"class="solr.TrieDoubleField"precisionStep="0"omitNorms="true"
- positionIncrementGap="0"/>
- ...
- </types>
- ...
- </schema>
必要的时候fieldType还需要自己定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤,如下:
- <fieldTypename="text_ws"class="solr.TextField"positionIncrementGap="100">
- <analyzer>
- <tokenizerclass="solr.WhitespaceTokenizerFactory"/>
- </analyzer>
- </fieldType>
- <fieldTypename="text"class="solr.TextField"positionIncrementGap="100">
- <analyzertype="index">
- <!--这个分词包是空格分词,在向索引库添加text类型的索引时,Solr会首先用空格进行分词
- 然后把分词结果依次使用指定的过滤器进行过滤,最后剩下的结果,才会加入到索引库中以备查询。
- 注意:Solr的analysis包并没有带支持中文的包,需要自己添加中文分词器,google下。
- -->
- <tokenizerclass="solr.WhitespaceTokenizerFactory"/>
- <!--inthisexample,wewillonlyusesynonymsatquerytime
- <filterclass="solr.SynonymFilterFactory"synonyms="index_synonyms.txt"
- ignoreCase="true"expand="false"/>
- -->
- <!--Caseinsensitivestopwordremoval.
- addenablePositionIncrements=trueinboththeindexandquery
- analyzerstoleavea'gap'formoreaccuratephrasequeries.
- -->
- <filterclass="solr.StopFilterFactory"
- ignoreCase="true"
- words="stopwords.txt"
- enablePositionIncrements="true"
- />
- <filterclass="solr.WordDelimiterFilterFactory"generateWordParts="1"
- generateNumberParts="1"catenateWords="1"catenateNumbers="1"
- catenateAll="0"splitOnCaseChange="1"/>
- <filterclass="solr.LowerCaseFilterFactory"/>
- <filterclass="solr.SnowballPorterFilterFactory"language="English"
- protected="protwords.txt"/>
- </analyzer>
- <analyzertype="query">
- <tokenizerclass="solr.WhitespaceTokenizerFactory"/>
- <filterclass="solr.SynonymFilterFactory"synonyms="synonyms.txt"ignoreCase="true"
- expand="true"/>
- <filterclass="solr.StopFilterFactory"
- ignoreCase="true"
- words="stopwords.txt"
- enablePositionIncrements="true"
- />
- <filterclass="solr.WordDelimiterFilterFactory"generateWordParts="1"
- generateNumberParts="1"catenateWords="0"catenateNumbers="0"
- catenateAll="0"splitOnCaseChange="1"/>
- <filterclass="solr.LowerCaseFilterFactory"/>
- <filterclass="solr.SnowballPorterFilterFactory"language="English"
- protected="protwords.txt"/>
- </analyzer>
- </fieldType>
2、再来看下fields节点内定义具体的字段(类似数据库的字段),含有以下属性:
- name:字段名
- type:之前定义过的各种FieldType
- indexed:是否被索引
- stored:是否被存储(如果不需要存储相应字段值,尽量设为false)
- multiValued:是否有多个值(对可能存在多值的字段尽量设置为true,避免建索引时抛出错误)
- <fields>
- <fieldname="id"type="integer"indexed="true"stored="true"required="true"/>
- <fieldname="name"type="text"indexed="true"stored="true"/>
- <fieldname="summary"type="text"indexed="true"stored="true"/>
- <fieldname="author"type="string"indexed="true"stored="true"/>
- <fieldname="date"type="date"indexed="false"stored="true"/>
- <fieldname="content"type="text"indexed="true"stored="false"/>
- <fieldname="keywords"type="keyword_text"indexed="true"stored="false"multiValued="true"/>
- <!--拷贝字段-->
- <fieldname="all"type="text"indexed="true"stored="false"multiValued="true"/>
- </fields>
3、建议建立一个拷贝字段,将所有的 全文本 字段复制到一个字段中,以便进行统一的检索:
以下是拷贝设置:
- <copyFieldsource="name"dest="all"/>
- <copyFieldsource="summary"dest="all"/>
4、动态字段,没有具体名称的字段,用dynamicField字段
如:name为*_i,定义它的type为int,那么在使用这个字段的时候,任务以_i结果的字段都被认为符合这个定义。如name_i,school_i
- <dynamicFieldname="*_i"type="int"indexed="true"stored="true"/>
- <dynamicFieldname="*_s"type="string"indexed="true"stored="true"/>
- <dynamicFieldname="*_l"type="long"indexed="true"stored="true"/>
- <dynamicFieldname="*_t"type="text"indexed="true"stored="true"/>
- <dynamicFieldname="*_b"type="boolean"indexed="true"stored="true"/>
- <dynamicFieldname="*_f"type="float"indexed="true"stored="true"/>
- <dynamicFieldname="*_d"type="double"indexed="true"stored="true"/>
- <dynamicFieldname="*_dt"type="date"indexed="true"stored="true"/>
schema.xml文档注释中的信息:
1、为了改进性能,可以采取以下几种措施:
- 将所有只用于搜索的,而不需要作为结果的field(特别是一些比较大的field)的stored设置为false
- 将不需要被用于搜索的,而只是作为结果返回的field的indexed设置为false
- 删除所有不必要的copyField声明
- 为了索引字段的最小化和搜索的效率,将所有的 text fields的index都设置成field,然后使用copyField将他们都复制到一个总的 text field上,然后对他进行搜索。
- 为了最大化搜索效率,使用java编写的客户端与solr交互(使用流通信)
- 在服务器端运行JVM(省去网络通信),使用尽可能高的Log输出等级,减少日志量。
2、<schema name="example" version="1.2">
- name:标识这个schema的名字
- version:现在版本是1.2
3、filedType
<fieldType name="string class="solr.StrField sortMissingLast="true omitNorms="true" />
- name:标识而已。
- class和其他属性决定了这个fieldType的实际行为。(class以solr开始的,都是在org.appache.solr.analysis包下)
可选的属性:
- sortMissingLast和sortMissingFirst两个属性是用在可以内在使用String排序的类型上(包括:string,boolean,sint,slong,sfloat,sdouble,pdate)。
- sortMissingLast="true",没有该field的数据排在有该field的数据之后,而不管请求时的排序规则。
- sortMissingFirst="true",跟上面倒过来呗。
- 2个值默认是设置成false
StrField类型不被分析,而是被逐字地索引/存储。
StrField和TextField都有一个可选的属性“compressThreshold”,保证压缩到不小于一个大小(单位:char)
fieldType name="text="solr.TextField positionIncrementGap="100">
solr.TextField 允许用户通过分析器来定制索引和查询,分析器包括 一个分词器(tokenizer)和多个过滤器(filter)
tokenizer class="solr.WhitespaceTokenizerFactory" />
空格分词,精确匹配。
filter ="solr.WordDelimiterFilterFactory generateWordParts="1 generateNumberParts catenateWords catenateNumbers catenateAll="0 splitOnCaseChange="1" />
在分词和匹配时,考虑 "-"连字符,字母数字的界限,非字母数字字符,这样 "wifi"或"wi fi"都能匹配"Wi-Fi"。
="solr.SynonymFilterFactory synonyms="synonyms.txt ignoreCase expand" />
同义词
="solr.StopFilterFactory words="stopwords.txt enablePositionIncrements" />
stopword:即在建立索引过程中(建立索引和搜索)被忽略的词,比如is this等常用词。在conf/stopwords.txt维护。
4、fields
field ="id type indexed stored required" />
- name:标识而已。
- type:先前定义的类型。
- indexed:是否被用来建立索引(关系到搜索和排序)
- stored:是否储存
- compressed:[false],是否使用gzip压缩(只有TextField和StrField可以压缩)
- mutiValued:是否包含多个值
- omitNorms:是否忽略掉Norm,可以节省内存空间,只有全文本field和need an index-time boost的field需要norm。(具体没看懂,注释里有矛盾)
- termVectors:[false],当设置true,会存储 term vector。当使用MoreLikeThis,用来作为相似词的field应该存储起来。
- termPositions:存储 term vector中的地址信息,会消耗存储开销。
- termOffsets:存储 term vector 的偏移量,会消耗存储开销。
- default:如果没有属性需要修改,就可以用这个标识下。
="false multiValued" />
包罗万象(有点夸张)的field,包含所有可搜索的text fields,通过copyField实现。
copyField source="cat dest="text" />
在添加索引时,将所有被拷贝field(如cat)中的数据拷贝到text field中
作用:
- 将多个field的数据放在一起同时搜索,提供速度
- 将一个field的数据拷贝到另一个,可以用2种不同的方式来建立索引。
dynamicField ="*_i="int" />
如果一个field的名字没有匹配到,那么就会用动态field试图匹配定义的各种模式。
- "*"只能出现在模式的最前和最后
- 较长的模式会被先去做匹配
- 如果2个模式同时匹配上,最先定义的优先
="*="ignored multiValued="true" />
如果通过上面的匹配都没找到,可以定义这个,然后定义个type,当String处理。(一般不会发生)
但若不定义,找不到匹配会报错。
5、其他一些标签
uniqueKey>id</>
文档的唯一标识,必须填写这个field(除非该field被标记required="false"),否则solr建立索引报错。
defaultSearchField>text>
如果搜索参数中没有指定具体的field,那么这是默认的域。
solrQueryParser defaultOperator="OR" />
配置搜索参数短语间的逻辑,可以是"AND|OR"。