注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Koala++'s blog

计算广告学 RTB

 
 
 

日志

 
 

企业级搜索引擎Solr 第二章 Schema和文本分析(Schema and Text Analysis)[2]  

2012-08-17 13:49:14|  分类: 搜索引擎 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Schema and Text Analysis

Author: David Smiley Eric Pugh

译者:Koala++ / 屈伟

The schema.xml file

         我们最终来看Solr Schema

         在我们开始之前,你先找到schema.xml文件。这个文件在一个Solr实例的conf目录下。它在Solrexample/solr/conf/schema.xml位置。这个示例schema.xml中有一些有用的域类型,以及详细的说明,和为示例数据的域定义。

         schema.xml文件开始处有:

<schema name="musicbrainz" version="1.4">

         我们设置schemamusicbrainz,即我们应用的名字。如果我们用不同的schema文件,我们可以将它们命名不同的名字以区别它们。

Defining field types

         Schema配置文件第一部分是配置域的数据类型。这部分到</types>结束,这部分配置占了文件的相当多一部分内容。域类型声明了域的数据类型,比如布尔,数值,时间,或是文本。这些定义会被<fields>中的域定义引用,下面是一个类型为boolean的域类型:

<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>

         一个域的类型有一个唯一的名字,并且这个类型是由class属性指定的一个Java类实现的。

         包括nameclass在内的大部分属性都适用于所有类型,比如omitNorms,也有一些属性只适用一些特定的类。它们通常可以在域声明的时候被覆盖。除了这些属性外,还有一些属性只适用于文本域。它们会在本章后来的内容介绍。

Built-in field type classes

         Solr有很多的内置域类型,几乎所有的类型都在Solr示例的schema.xml中有详细的介绍。这里我们不会一一列举它们,但是会详细介绍几个重要的域类型。

Numbers and dates

         Solr至少有五种不同的域类型来保存一个整型,如果你算上string类型,那就是六种!对floatdoublelongdate也是一样,也至少有五种类型。这也许和你想的Solr只处理文本的不一样。我后面会以Integer为例解释何时使用它们。以“Trie”开头的类型可以满足你95%的需求

l  tieIntField(有precisionStep=0),通常称为“int”。它对大部分应用场景都是适合的。

l  tieIntField(有precisionStep>0),通常称为“tint”。如果你想在很多值的域上进行数值区间查询(包括facet区间),那么这种域类型在查询时有着极好的性能,但需要在索引时多消耗一点索引空间和时间。 Solr的示例配置中数值类型的precisionStep设置为8date类型为6,我推荐你使用这种默认设置。因为如果你选择更小的precisionStep值(但>0),会导致Solr会为提高区间查询性能而增加索引的空间和时间。

l  srtableIntField,通常称为“sint”。与Trie相似,有precisionStep=0,这个类型还支持sortMissingFirstSortMissingLast属性。

l  intField,通常称为“pint”。这是一个旧的实现,请不要使用它。

l  BCDIntFIeldBinary Coded Decimal)。不会费神知道它是什么。

所有的数值类型都会以它们的数值排序而不是按字典序排序。

最后,还有一个域类型为ExternalFileField,它能从一个纯文本文件中,而不索引中读取float类型值。它是用于处理要进行排序或影响打分的域变化很快的情况的(比如,按投票或是点击率排序),用这种类型不用再对文档建索引。注意Lucene底层无法单独更新一个域,整个文档都需要重建索引。这是特殊情况的临时解决方法,在第五章,Search Relevancy还会再介绍。

Geospatial

         我们将在第四章来介绍它。

Field options

         下面介绍的属性适用于大部分域类型,但不是全部域类型。

l  indexed:表示这个域可以被搜索和排序。不被索引的域的唯一用途就是作为搜索结果返回。

?  sortMissingLastsortMissingFirst:如果设置这两个属性为true,会指定排序时域值为空时会排在前面或是后面,而不管是升序还是逆序排序。默认行为是缺失值的文档在升序排序时排在前面,而降序时排到后面。

?  omitNorms:(高级)如果你不想域值的长度影响得分(见第五章)或是它根本就不参与排序(比如用于faceting),如果你在索引时进行文档boosting(下章介绍),你可以设置它。除了它对得分的影响,它还可以节省一点内存。

?  omitTermFreqAndPositions:(高级)在索引时忽略词频和词的位置以节约一些空间。后果是词组索引不能使用并且得分准确性受影响。

?  termVectors:(高级)告诉Lucene保存一些信息以在某些情况下提升搜索性能。比如,一个域要用MoreLikeThis特征,或是高亮比较长的文本域,那么设置这个属性。它会极大地增加索引的大小和索引的时间,所以你要设置它,请进行设置前后的对比实验。还有两个属性termPositionstermOffsets会添加更多的信息到词向量中。FastVectorHighlighter需要这两个属性。

?  positionIncrementGap:(高级)对一个multiValued域,这是设置在两个域值之间有多少虚拟的词,这是为了防止词组匹配时意外匹配相邻的域值。比如,如果AB是一个域的两个值,如果positionIncrementGap设置大于1,那么词组匹配会阻止“AB”被匹配。

l  stored:表明这个域可以在搜索结果中出现。通常域是被存储的,但有时同一域会被拷贝到多个域分别存储,所以这个域不会被标记为stored

?  compressed:不再支持。这个选项从Solr v1.4被移除了。因为开发者对它的实现不满意。

l  multiValues:设置这个属性可以让一个域包含多个值。值的顺序是与输入时一致的。

Field definitions

         Schema中域的定义在<fields>元素内,除了上面描述的域的选项,一个域还可以有下面的属性:

l  name:唯一标识这个域的名字,名字的值在字符上没有限制,任何词都可以用,除了score

l  type:引用Schema前面定义的域值。

l  default:(可选)当文档中没有这个域的值时,所用的默认值。一个常用的设置文档时间戳的配置<fieldname="indexedAt" type="tdate" default="NOW/SECOND" />,在第四章DateMath会介绍更多关于date的内容。

l  required:(可选)设置为true,在文档中相应域没有值时,建索引会失败。

Dynamic field definitions

         动态域定义的概念,它展示了Lucene相比典型的关系数据库索引的灵活性,在Solr中你不但可以明确地指定域的名字,也可以直接使用建索引时文档中提供的名字。Solr的示例Schema中提供一个例子,如下:

<dynamicField name="*_dt" type="date" indexed="true" stored="true"/>

         如果在建索引的时候,如果一个文档中的一个域既与一个明确的域定义匹配,又与一个动态域定义模式匹配(比如update_dt,它匹配*_dt),那么会选择明确的域定义名字。动态域定义和普通域定义格式一样,但元素的名字是dynamicField,并且它的name属性必须以星号开头或是结尾。也可以只有*一个字符,表示匹配所有。

         最后,无论是明确定义的域或是动态定义的域,它都是域,动态定义域只是方便地定义schema的一种方式。动态定义域方式不会对性能造成影响。

Our MusicBrainz field definitions

         下面是我们的MusicBrainz Schema定义的第一部分。下面是有一些域为是后面章节介绍其它搜索属性而加入的。下面的配置是一个结合Schemacombined schema),它定义了所有的索引实体类型:artistsreleasetracks。定义的方法在本章前面的内容已经介绍过了。注意我在域的名字前加入加了实体名的前缀(a_r_t_),以避免与其它实体的域名冲突。我们还在denormalize的时候使用像这样的缩写域名r_a_name(一个ReleaseArtist的名字)。

<!-- COMMON TO ALL TYPES: -->

<field name="id" type="string" required="true" />

<!-- Artist:11650 -->

<field name="type" type="string" required="true" />

<!-- Artist | Release | Label -->

<field name="indexedAt" type="tdate" default="NOW/SECOND" />

<!-- ARTIST: -->

<field name="a_name" type="title" />

<!-- The Smashing Pumpkins -->

<field name="a_name_sort" type="string" stored="false" />

<!-- Smashing Pumpkins, The -->

<field name="a_alias" type="title" stored="false" multiValued="true"

/>

<field name="a_type" type="string" />

<!-- group | person -->

<field name="a_begin_date" type="tdate" />

<field name="a_end_date" type="tdate" />

<field name="a_member_name" type="title" multiValued="true" />

<!-- Billy Corgan -->

<field name="a_member_id" type="long" multiValued="true" />

<!-- 102693 -->

<!-- RELEASE -->

<field name="r_name" type="title" />

<!-- Siamese Dream -->

<field name="r_name_sort" type="string" stored="false" />

<!-- Siamese Dream -->

<field name="r_a_name" type="title" />

<!-- The Smashing Pumpkins -->

<field name="r_a_id" type="long" />

<!-- 11650 -->

<field name="r_attributes" type="int" indexed="false"

multiValued="true" />

<!-- ex: 0, 1, 100 -->

<field name="r_type" type="rType" stored="false" multiValued="true" />

<!-- Album | Single | EP |... etc. -->

<field name="r_official" type="rOfficial" stored="false"multiValued="

true" />

<!-- Official | Bootleg | Promotional -->

<field name="r_lang" type="string" indexed="false" />

<!-- eng / latn -->

<field name="r_tracks" type="int" indexed="false" />

<field name="r_event_country" type="string" multiValued="true" />

<!-- us -->

<field name="r_event_date" type="tdate" multiValued="true" />

<!-- TRACK -->

<field name="t_name" type="title" />

<!-- Cherub Rock -->

<field name="t_num" type="int" indexed="false" />

<!-- 1 -->

<field name="t_duration" type="int"/>

<!-- 298133 -->

<field name="t_a_id" type="long" />

<!-- 11650 -->

<field name="t_a_name" type="title" />

<!-- The Smashing Pumpkins -->

<field name="t_r_name" type="title" />

<!-- Siamese Dream -->

<field name="t_r_tracks" type="int" indexed="false" />

<!-- 13 -->

         注意我们指定required的域是对所有类型都通用的,即IDtype域,因为我们正在进行结合索引的Schema配置。

         在我们的Schema中我们选择对大部分域进行索引,尽管在MusicBrainz搜索中只能对每种实体的名字搜索 。我们这样做是想让Schema变得更有趣一些,以展示更多的Solr的能力。

Copying fields

         与域定义紧密相关的配置是copyFieldcopyField配置在索引时将一个或多个输入域的值拷贝到另一个域。一个copyField配置如下:

<copyField source="r_name" dest="r_name_sort" maxChars="20" />

         在当你想将一个域的值以不同的方式索引时,这个配置就发挥它的作用了。比如,排序和Faceting需要单个索引值。在搜索技巧中另一个常用的方法是将多个域的值拷贝到一个域去,这个域不使用norm也不进行排序。这可以使搜索只搜索 一个域而不是多个域,从而在牺牲得分质量的代价下可以极大的提高搜索性能。这种技巧通常还会搜索另几个有着较高boost的域以弥补得分的影响。在本章后面介绍的dismax查询解析器,会使这变得容易。

         在索引的时候,输入数据中的每个域的名字都会与所有copyField配置中的域名比较。source属性可以会使用*通配符,所以输入数据的域可能会匹配多于一个copyField。如果通配符在destination中使用,则它必须引用的是一个动态域(dynamic field),并且这时source中也必须使用通配符,否则就会报错。一个匹配source属性指定域的值都会拷贝到dest属性中指定的域中。如果指定了可选maxChar属性,则最多拷贝配置值的字符数。拷贝不会覆盖dest域中的原有数据,所以如果要拷贝多个域,记得可能需求指定multiValued

The unique key

         在接近schema的最下面是<uniqueKey>声明,它指定每个文档的唯一ID,如果这个ID存在。下面是我们在MusicBrainz Schema中的配置:

<uniqueKey>id</uniqueKey>

         尽管这个配置不是强制要求的,但是你应该定义一个唯一ID域。在我们的MusicBrainz Schema中,ID是一个字符串,它有实体类型的前缀,所以是全局唯一的,比如Artist:11650。如果你的源数据中没有一个ID域,你可以考虑用Universally Unique Identifier,一个遵循RFC-4122标准的UUID。你只需要有一个class属性值为solr.UUIDField的域类型的域,或是将域的defaultField的值为一个特殊值“NEW”,这样Solr就会自动产生UUIDSolrUUID是基于java.util.UUID的。

The default search field and query operator

         在接近Schema文件的底部有两个配置元素指定在解析一个查询字符串时域默认的搜索行为:

<!-- <defaultSearchField>text</defaultSearchField>

<solrQueryParser defaultOperator="AND"/> -->

         其中defaultSearchField指定了如果查询中没有明确指定要查询的域时默认的查找域。而solrQueryParser配置中的defaultOperator属性可以让你指定默认的搜索操作(AND或是OR)。这些对于Solr请求处理器处理查询时是非常重要的默认值。我强烈建议你忽略solrQueryParserdeaultOperator属性,也不要依赖defaultSearchField。这些配置可以在solrconfig.xml中进行配置。

 
  评论这张
 
阅读(3448)| 评论(1)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017