首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Hibernate Search(基于version3.4)-第四章Mapping entities to the index structure

2012-07-26 
Hibernate Search(基于version3.4)--第四章Mapping entities to the index structureMapping entities to

Hibernate Search(基于version3.4)--第四章Mapping entities to the index structure

Mapping entities to the index structure

?

4.1. 映射一个实体(Mapping an entity)

在第一章中,你已经知道了建立实体索引的所有元信息是通过注解描述的,所以不需要xml的映射文件。但是你依然可以使用Hibernate的映射文件来配置基本的Hibernate映射,但Hibernate Search的配置只能通过注解来表达。

?

4.1.1.基本映射(Basic mapping)

我们先介绍最常使用的注解。

?

4.1.1.1. @Indexed

首先,我们必须要声明一个持久化类是可索引的。这可以由注解@Indexed来注明,所有没有@Indexed的实体将忽略indexing步骤。

?

Example 4.1. Making a class indexable with @Indexed

?

Example 4.3, “Using @Fields to map a property multiple times”中,summary属性域被索引了两次,一次是以summary作为索引文档的域名,以tokenized的方式建立索引,另一次是以summary_forSort作为索引文档的域名,以untokenized的方式建立索引。在@Fields中,@Field支持两个有用的属性:

analyzer:定义@Analyzer注解针对具体的lucene field而不是实体内中的属性域。bridge:定义@FieldBridge注解针对具体的lucene field而不是实体内中的属性域。

关于@Analyzer和@FieldBridge,下面的章节有更详细的说明。

?

?

4.1.3. 嵌入和关联对象(Embedded and associated objects)

关联对象和嵌入的对象都可以被索引作为根实体索引的一部分。当实体内中的属性域为关联对象时,这就会显得非常的有用。

?

假设在Example 4.4, “Indexing associations”例子中,它的目的是想要返回city为Atlanta的place,那么在Lucene query parser language中,它会被解析为address.city:Atlanta。例子中会建立名为Place的index,该index会包含这些field: address.id, address.street和address.city,这些field都可以用于搜索。

?

Example 4.4. Indexing associations

?

?

Tip :Filters 和 char filters会按他们在@AnalyzerDef中定义的顺序来应用的。因些顺序是重要的。

?

有些tokenizers, token filters 或char filters需要加载资源文件(比如配置文件,元数据文件等)。stop filter和synonym filter就需要这样的文件。如果资源文件的charset与VM默认的不一样,你可以通过resource_charset 参数明确地指定资源文件的charset。

?

Example 4.11. Use a specific charset to load the property file

?

?

?

?

一旦定义了一个Analyzer,它就可以通过@Analyzer注解来重用。如Example 4.12, “Referencing an analyzer by name”.所示。

?

Example 4.12. Referencing an analyzer by name

?noneHTMLStripCharFilterFactory?移除HTML中标准的标签,保留文本内容?none?none

?

?

Table 4.2. Example of available tokenizers

FactoryDescriptionParametersAdditional
dependenciesStandardTokenizerFactory使用Lucene的StandardTokenizernonenoneHTMLStripCharFilterFactory移除HTML中标准的标签,保留文本容,之后交由StandardTokenizer处理nonesolr-corePatternTokenizerFactory

通过一个指定的正则表达式来划分词语。

pattern:用于划分词语的正则表达式。

group:says which pattern group to extract into tokens

solr-core

?

Table 4.3. Examples of available filters

?

FactoryDescriptionParametersAdditional
dependenciesStandardFilterFactory从token中移除'.'和''s'nonesolr-coreLowerCaseFilterFactory小写所有的tokennonesolr-coreStopFilterFactory移除与列表中的stop word匹配的token

words:指向一个包含stop words的资源文件

ignoreCase:与stop word的比较是否要忽略大小写

solr-coreSnowballPorterFilterFactory

把一个单词还原为它的词干形式(像protect, protects,
protection都会使用protect作为token)

language:Danish,Dutch, English,Finnish, French,German, Italian,Norwegian,Portuguese, Russian,Spanish, Swedish 或其他语言solr-coreISOLatin1AccentFilterFactory

移除发音符,比如French(法语)

nonesolr-corePhoneticFilterFactory

向token stream插入发音相似的单词作为相似token(similar token)

encoder:值为DoubleMetaphone,Metaphone, Soundex或RefinedSoundex之一。

?

inject:true就插入新的token到token stream,false就替代现有的token。

?

maxCodeLength:设置可生成code的最大长度。只支持Metaphone和DoubleMetaphone encoder。

solr-core and commons-codecCollationKeyFilterFactory

转换每个token成java.text.CollationKey,并使用IndexableBinaryStringTools对java.text.CollationKey进行编码,从而把它保存到index term。

?

?custom,? language,country,? variant,strength,decomposition? see Lucene's CollationKeyFilter javadocs for more info?solr-core and commons-io

?

我们推荐通过IDE工具查看org.apache.solr.analysis.TokenizerFactory和org.apache.solr.analysis.TokenFilterFactory的所有可用的实现。

?

4.3.3. 动态解析器选择(试验性的)(Dynamic analyzer selection (experimental))

到目前为止,我们所定义的analyzer都是静态的。然而,可能有这样的需求,我们需要根据实体类的具体状态来决定使用哪个analyzer,比如说在一个多语言的应用环境中。拿Example 4.13, “Usage of @AnalyzerDiscriminator”中的BlogEntry类来说,analyzer需要根据language属性来决定使用哪个analyzer,那么对词干(stemmer)解析就可以指定正确的语言来解析文本。

?

Hibernate Search引进了AnalyzerDiscriminator注解来实现Dynamic analyzer selection。Example 4.13, “Usage of @AnalyzerDiscriminator”展示了这个注解的使用。

?

Example 4.13. Usage of @AnalyzerDiscriminator

?

在这个例子中,song title被索引在两个field中,title field使用的是standard analyzer,而title_stemmed使用的是stemming analyzer。query会根据对应的field使用了合适的analyzer。

?

Tip :通过@AnalyzerDef定义的analyzer,你同样通过searchFactory.getAnalyzer(String)来获取。

?

4.4. Bridges

在我们讨论实体类的基本映射的时候,一个很重要的因素一直被我们忽略。在Lucene所有的index field必须渲染为字符串类型。所有标注为@Field的属性域都要转换为String来建立索引。我们到现在才提出这个问题是因为在大多数情况下,Hibnerate Search都会自动地完成转换工作,这些工作都由内建的bridge完成的。然而,有些时候你需要一个更好的控制这个转换过程。

?

4.4.1. Built-in bridges

Hibernate Search捆绑了大量的bridge完成Java属性类型到字符串的转换。

?

?

?

Hibernate Search comes bundled with a set of built-in bridges between a Java property type and
its full text representation.

?

null:默认地,null值不会被索引。Lucene也不支持null元素。然而有时候使用一个自定义的token来代替null值会显得非常有用。 See Section 4.1.1.2, “@Field” for more information

?

java.lang.String:按原本的值来索引。

?

short, Short, integer, Integer, long, Long, float, Float, double, Double, BigInteger, BigDecimal的数值型类型:转换到字符串的表示形式。注意,Lucene不能自动完成数值型的对比工作(如在range query中),它们需要补齐(padded)。

?

Note :使用range query是有争议的而且有一些缺点。一个可选的方法是使用一个Filter query,它可以过滤一个查询到合适的范围。Hibernate Search支持补齐机制(padding mechanism)。

?

java.util.Date:日期型保存成yyyyMMddHHmmssSSS的字符串形式 (例如200611072203012表示2006年11月7日 22:03 12ms) 。你不必为它的格式化忧心,重要的是,当你使用DateRange查询的时候,你需要知道日期应该表示成GMT形式。

?

一般来说,保存的Date不需要精确到毫秒。@DateBridge定义了合适的解决方法让你去保存Date到index。@DateBridge(resolution=Resolution.DAY)定义了Date只保存到具体的'日',而不是毫秒。

?

?

你可以使用通过@FieldBridge注解的impl参数应用上面定义的StringBridge。

?

ParameterizedBridge接口可以与StringBridge,TwoWayStringBridge,FieldBridge一起实现。所有的实现必须是线程安全的,参数必须在初始化时设置。

?

4.4.2.1.2. 按类型的bridge(Type aware bridge)

?

有时候能知道bridge应用在哪个类型上面是非常有用的:

知道getter方法返回类型的bridge知道类的类型通过类级别的bridge

一个例子是bridge处理enums在一种自定义的形式,但在访问时应用实际的enum类型。任何实现了 AppliedOnTypeAwareBridge接口的bridge会自动的注入所需要的类型。像parameters一样,类型注入不需要关心线程安全。

?

?

4.4.2.1.3. 两种方式的bridge(Two-way bridge)

如果你的bridge实现应用在id属性(使用了@DocumentId注解),你需要使用TwoWayStringBridge接口,该接口继承于StringBridge接口。Hibernate Search需要读取id的字符串表示并生成对象表示形式。同样也是使用@FieldBridge注解。

?

Example 4.17. Implementing a TwoWayStringBridge usable for id properties

?

?

?

4.4.2.2. FieldBridge

有些用例不仅仅是把对象转换成字符串来映射属性到lucene index中,但实现FieldBridge会让你得到最大的灵活性。该接口为你提供了属性值,并让你按你所希望的方式映射到Lucene Document。比如说你希望把一个属性域保存在两个不同的document field中。这个接口的概念与Hibernate UserType非常类似。

?

Example 4.18. Implementing the FieldBridge interface

?

在Example 4.18, “Implementing the FieldBridge interface”中,fields并不是直接地添加到Document。相反,添加操作委托给LuceneOptions helper;helper会应用注解中的@Field的选项,像Store,TermVector或@Boost值。这也用于封装复杂的COMPRESS的实现。虽然委托LuceneOptions去添加fields到Document是推荐的,但你也可以直接编辑Document和忽略LuceneOptions。

?

Tip :像LuceneOptions这些类从Lucene API中变化而来的,它们作用是保护你的应用和简化代码。你可以使用它们,但并不是必须的。

?

4.4.2.3. ClassBridge

有时候组合一个实体的多个属性到Lucene index中会很有用的。@ClassBridge包含一个或多个@ClassBridge可以定义在class级别。在这种情况下, 自定义的field bridge的value参数不再是属性域的值,而是该实体实例。@ClassBridge支持termVector属性。

?

Example 4.19. Implementing a class bridge

?

在这个例子中, CatFieldsClassBridge被应用到 department实例,field bridge结合了branch和network属性域并添加到index。

?

4.5. Providing your own id

Warning :这部分文档的工作还在进行中。

?

如果你扩展了Hibernate Search内部功能,你可以提供你自己的id。你可以生成唯一的id值添加到index中去。它必须在创建an org.hibernate.search.Work的时候提供给Hibernate Search——document id是构造器中的一个参数。

?

4.5.1. The ProvidedId annotation

@PrivideId与@DocumentId不一样,它是标注在类级别上的。你可以通过bridge属性来指定一个自定义的bridge实现。同样地,如果你使用@ProvidedId注解一个类,该类的子类也会也会得到该注解,但是它不是通过@Inherited得到这种效果的。另外,要确保@ProvidedId与@DocumentId不能同时使用,否则你的系统就会崩溃。

?

Example 4.20. Providing your own id

@ProvidedId (bridge = org.my.own.package.MyCustomBridge)@Indexedpublic class MyClass{    @Field    String MyString;    ...}

?

4.6. Programmatic API?

Warning:该功能还在测试阶段。API在以后可能会有所改变。

?

略。?

?

?

?

?

?

?

热点排行