11.4. 嵌入式搜索


当 Data Grid 用作库时,可以使用嵌入式搜索。不需要 protobuf 映射,并在 Java 对象之上进行索引和搜索。

11.4.1. 快速示例

我们将将 Book 实例存储在名为"books"的数据网格缓存中。将对本书实例进行索引,因此我们为缓存启用索引:

Data Grid 配置:

infinispan.xml

<infinispan>
    <cache-container>
        <transport cluster="infinispan-cluster"/>
        <distributed-cache name="books">
            <indexing>
                <indexed-entities>
                    <indexed-entity>com.acme.Book</indexed-entity>
                </indexed-entities>
            </indexing>
        </distributed-cache>
    </cache-container>
</infinispan>

获取缓存:

import org.infinispan.Cache;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;

EmbeddedCacheManager manager = new DefaultCacheManager("infinispan.xml");
Cache<String, Book> cache = manager.getCache("books");

每个 Book 将按照以下示例定义;我们必须选择索引哪些属性;对于每个属性,我们可以选择使用 Hibernate Search 项目中定义的注释选择高级索引选项。

Book.java

import org.hibernate.search.annotations.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

//Values you want to index need to be annotated with @Indexed, then you pick which fields and how they are to be indexed:
@Indexed
public class Book {
   @Field String title;
   @Field String description;
   @Field @DateBridge(resolution=Resolution.YEAR) Date publicationYear;
   @IndexedEmbedded Set<Author> authors = new HashSet<Author>();
}

Author.java

public class Author {
   @Field String name;
   @Field String surname;
   // hashCode() and equals() omitted
}

假设我们在我们的 Data Grid Cache 中存储了多个 Book 实例,我们可以根据以下示例所示搜索任何匹配字段。

QueryExample.java

// get the query factory from the cache:
QueryFactory queryFactory = org.infinispan.query.Search.getQueryFactory(cache);

// create an Ickle query that will do a full-text search (operator ':') on fields 'title' and 'authors.name'
Query<Book> fullTextQuery = queryFactory.create("FROM com.acme.Book WHERE title:'infinispan' AND authors.name:'sanne'")

// The ('=') operator is not a full-text operator, thus can be used in both indexed and non-indexed caches
Query<Book> exactMatchQuery = queryFactory.create("FROM com.acme.Book WHERE title = 'Programming Infinispan' AND authors.name = 'Sanne Grinnovero'")

// Full-text and non-full text operators can be part of the same query
Query q = queryFactory.create("FROM com.query.Book b where b.author.name = 'Stephen' and b.description : (+'dark' -'tower')");

// get the results
List<Book> found=query.execute().list();

除了 list () 外,您还可以选择获取 迭代器 () 或使用分页。

11.4.2. 映射实体

网格依赖于 Hibernate Search 的丰富 API,以定义在实体级别索引的精细配置。此配置包括注解哪些字段,这些分析器应使用,如何映射嵌套对象等。Hibernate Search 手册中 提供了详细的文档。

11.4.2.1. @DocumentId

与 Hibernate Search 不同,使用 @DocumentId 将字段标记为标识符不适用于 Data Grid 值;在 Data Grid 中,所有 @Indexed 对象的标识符是用于存储值的密钥。您仍然可以使用 @Transformable、自定义类型和自定义 FieldBridge 实施的组合来自定义键的索引方式。

11.4.2.2. @Transformable 键

每个值的密钥也需要索引,必须在 String 中转换密钥实例。Data Grid 包括一些默认的转换例程来编码常见的原语,但要使用一个自定义密钥,您必须提供一个 org.infinispan.query.Transformer 的实现。

通过注解注册密钥转换程序

您可以使用 org.infinispan.query.Transformable 标注密钥类,您的自定义转换器实施将自动获取:

@Transformable(transformer = CustomTransformer.class)
public class CustomKey {
   ...
}

public class CustomTransformer implements Transformer {
   @Override
   public Object fromString(String s) {
      ...
      return new CustomKey(...);
   }

   @Override
   public String toString(Object customType) {
      CustomKey ck = (CustomKey) customType;
      return ...
   }
}

通过缓存索引配置注册密钥转换程序

在嵌入式和服务器配置中使用 key-transformers xml 元素:

<replicated-cache name="test">
    <indexing auto-config="true">
        <key-transformers>
            <key-transformer key="com.mycompany.CustomKey" transformer="com.mycompany.CustomTransformer"/>
        </key-transformers>
    </indexing>
</replicated-cache>

或者,使用 Java 配置 API (embedded 模式):

   ConfigurationBuilder builder = ...
   builder.indexing().enable()
         .addKeyTransformer(CustomKey.class, CustomTransformer.class);

11.4.2.3. 程序映射

除了使用注解将实体映射到索引外,还可以以编程方式进行配置。

在以下示例中,我们映射了一个要存储在网格中的对象 Author,并可在两个属性上搜索,但没有注解类。

import org.apache.lucene.search.Query;
import org.hibernate.search.cfg.Environment;
import org.hibernate.search.cfg.SearchMapping;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.cache.Index;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.query.CacheQuery;
import org.infinispan.query.Search;
import org.infinispan.query.SearchManager;

import java.io.IOException;
import java.lang.annotation.ElementType;
import java.util.Properties;

SearchMapping mapping = new SearchMapping();
mapping.entity(Author.class).indexed()
       .property("name", ElementType.METHOD).field()
       .property("surname", ElementType.METHOD).field();

Properties properties = new Properties();
properties.put(Environment.MODEL_MAPPING, mapping);
properties.put("hibernate.search.[other options]", "[...]");

Configuration infinispanConfiguration = new ConfigurationBuilder()
        .indexing().index(Index.NONE)
        .withProperties(properties)
        .build();

DefaultCacheManager cacheManager = new DefaultCacheManager(infinispanConfiguration);

Cache<Long, Author> cache = cacheManager.getCache();
SearchManager sm = Search.getSearchManager(cache);

Author author = new Author(1, "Manik", "Surtani");
cache.put(author.getId(), author);

QueryBuilder qb = sm.buildQueryBuilderForClass(Author.class).get();
Query q = qb.keyword().onField("name").matching("Manik").createQuery();
CacheQuery cq = sm.getQuery(q, Author.class);
assert cq.getResultSize() == 1;
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.