2015-11-02 2 views
0

Я хочу, чтобы полный текстовый поиск адресов электронной почты в объекте, использующем Hibernate Search.Hibernate Search не индексирует адрес электронной почты?

Учитывая следующее юридическое лицо "Лицо" с индексированной поле "электронная почта":

Person.groovy

package com.example 

import javax.persistence.Entity 
import javax.persistence.GeneratedValue 
import javax.persistence.GenerationType 
import javax.persistence.Id 

import org.hibernate.search.annotations.Field 
import org.hibernate.search.annotations.Indexed 

@Entity 
@Indexed 
class Person { 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    Long id 

    @Field 
    String email 
} 

и дал Repository

SearchRepository.groovy
package com.example 

import javax.persistence.EntityManager 

import org.apache.lucene.search.Query 
import org.hibernate.search.jpa.FullTextEntityManager 
import org.hibernate.search.jpa.Search 
import org.hibernate.search.query.dsl.QueryBuilder 
import org.springframework.beans.factory.annotation.Autowired 
import org.springframework.stereotype.Repository 

@Repository 
class SearchRepository { 

    @Autowired 
    EntityManager entityManager 

    FullTextEntityManager getFullTextEntityManager() { 
     Search.getFullTextEntityManager(entityManager) 
    } 

    List<Person> findPeople(String searchText){ 
     searchText = searchText.toLowerCase()+'*' 
     QueryBuilder qb = fullTextEntityManager.searchFactory 
       .buildQueryBuilder().forEntity(Person).get() 
     Query query = 
       qb 
       .keyword() 
       .wildcard() 
       .onField('email') 
       .matching(searchText) 
       .createQuery() 

     javax.persistence.Query jpaQuery = 
       fullTextEntityManager.createFullTextQuery(query, Person) 

     jpaQuery.resultList 
    } 
} 

, то следующий тест не выполнен:

SearchWildcardTest.groovy

package com.example 

import javax.persistence.EntityManager 

import org.hibernate.search.jpa.FullTextEntityManager 
import org.hibernate.search.jpa.Search 
import org.junit.Test 
import org.junit.runner.RunWith 
import org.springframework.beans.factory.annotation.Autowired 
import org.springframework.boot.test.SpringApplicationConfiguration 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner 
import org.springframework.transaction.annotation.Transactional 

@RunWith(SpringJUnit4ClassRunner) 
@SpringApplicationConfiguration(classes = HibernateSearchWildcardApplication) 
@Transactional 
class SearchWildcardTest { 

    @Autowired 
    SearchRepository searchRepo 

    @Autowired 
    PersonRepository personRepo 

    @Autowired 
    EntityManager em 

    FullTextEntityManager getFullTextEntityManager() { 
     Search.getFullTextEntityManager(em) 
    } 

    @Test 
    void findTeamsByNameWithWildcard() { 
     Person person = personRepo.save new Person(email: '[email protected]') 

     fullTextEntityManager.createIndexer().startAndWait() 
     fullTextEntityManager.flushToIndexes() 

     List<Person> people = searchRepo.findPeople('[email protected]') 

     assert people.contains(person) // this assertion fails! Why? 
    } 
} 

PersonRepository.groovy

package com.example 

import org.springframework.data.repository.CrudRepository 

interface PersonRepository extends CrudRepository<Person, Long>{ 
} 

build.gradle

buildscript { 
    ext { 
     springBootVersion = '1.2.7.RELEASE' 
    } 
    repositories { 
     mavenCentral() 
    } 
    dependencies { 
     classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
     classpath('io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE') 
    } 
} 

apply plugin: 'groovy' 
apply plugin: 'eclipse' 
apply plugin: 'spring-boot' 
apply plugin: 'io.spring.dependency-management' 

jar { 
    baseName = 'hibernate-search-email' 
    version = '0.0.1-SNAPSHOT' 
} 
sourceCompatibility = 1.8 
targetCompatibility = 1.8 

repositories { 
    mavenCentral() 
} 

dependencies { 
    compile('org.springframework.boot:spring-boot-starter-data-jpa') 
    compile('org.codehaus.groovy:groovy') 
    compile('org.hibernate:hibernate-search:5.3.0.Final') 
    testCompile('com.h2database:h2') 
    testCompile('org.springframework.boot:spring-boot-starter-test') 
} 

task wrapper(type: Wrapper) { 
    gradleVersion = '2.8' 
} 

Вот что Лука показывает из сгенерированного индекса Lucene после выполнения теста:

enter image description here

Мне кажется, что адрес электронной почты «[email protected]» не полностью хранится в индексе, а вместо этого разрывается на две строки «foo» и «bar.com».

«Начало работы» руководство с официального Hibernate Search website утверждает, что

[...] Стандартный токенизатор разбивает слова на знаки препинания и дефисов, сохраняя при этом адреса электронной почты и интернет-хостов нетронутыми. Это хороший токенизатор общего назначения. [...]

Я, должно быть, здесь что-то не хватает, но не смог понять это.

Мои вопросы:

  • Почему мой код не индексировать полный адрес электронной почты?
  • Как достичь этого, чтобы проиндексировать адрес так, чтобы тест прошел?

ответ

3

Похоже, что документы не отражают изменения в базовых API-интерфейсах Lucene.

[K] eeping адреса электронной почты и интернет-хостов неповрежденные ...

Это используется, чтобы быть правильным для традиционного StandardTokenizer, который с тех пор был изменен на стороне Lucene. Его поведение можно найти в ClassicTokenizer в настоящее время.

Поэтому следующая конфигурация должна дать вам то, что вы после:

@Entity 
@Indexed 
@AnalyzerDef(
    name = "emailanalyzer", 
    tokenizer = @TokenizerDef(factory = ClassicTokenizerFactory.class), 
    filters = { 
     @TokenFilterDef(factory = LowerCaseFilterFactory.class), 
    } 
) 
class Person { 

    // ... 

    @Field 
    @Analyzer(definition = "emailanalyzer") 
    String email; 
} 

Обратите внимание, что обрезка также применяется с этой конфигурацией. Мы соответствующим образом адаптируем документацию по HSEARCH, спасибо за обнаружение этого!

+0

Отлично, @Gunnar! Это работает для меня, спасибо большое! – Riggs

+0

Ницца, рад слышать! – Gunnar

Смежные вопросы