2014-06-15 190 views
1

我正在用Hibernate Search 4.5.1和Spring 4.0.5.RELEASE構建一個應用程序。我試圖索引以下類:Hibernate搜索沒有返回結果

@Entity 
@Indexed 
@Analyzer(impl= org.apache.lucene.analysis.standard.StandardAnalyzer.class) 
@Table(name="SONG") 
@XmlRootElement(name="song") 
public class Song 
{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "ID", updatable = false, nullable = false) 
    private Long id; 

    @Field(store = Store.YES) 
    @Column(name="NAME", length=255) 
    private String name; 

    @Field(store = Store.YES) 
    @Column(name="ALBUM", length=255) 
    private String album; 

    @Field(store = Store.YES) 
    @Column(name="ARTIST", length=255) 
    private String artist; 

    @NotNull 
    @Column(name="PATH", length=255) 
    private String path; 

    @NotNull 
    @Column(name="PATH_COVER", length=255) 
    private String cover; 

    @NotNull 
    @Column(name="LAST_VOTE") 
    private Date date; 

    @Field(store = Store.YES) 
    @NotNull 
    @Column(name="N_VOTES") 
    private int nvotes; 

    @NotNull 
    @Column(name="ACTIVE", nullable=false, columnDefinition="TINYINT(1) default 0") 
    private boolean active; 

    @OneToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="IMAGE_ID",insertable=true,updatable=true,nullable=false,unique=false) 
    private Image image; 

    @IndexedEmbedded 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "PLAYLIST_ID", nullable = false) 
    private PlayList playList; 

    @OneToMany(mappedBy = "song") 
    private Set<UserVotes> userServices = new HashSet<UserVotes>(); 

我建立一個JUnit測試案例,看起來像這樣:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"classpath:jukebox-servlet-test.xml"}) 
@Transactional 
public class SongDaoTest { 

    @Autowired 
    public I_PlaceDao placeDao; 
    @Autowired 
    public I_PlayListDao playListDao; 
    @Autowired 
    public I_SongDao songDao; 

    @Before 
    public void prepare() throws Exception 
    { 
      Operation operation = sequenceOf(CommonOperations.DISABLE_CONTRAINTS, CommonOperations.DELETE_ALL,CommonOperations.INSERT_SONG_DATA, CommonOperations.ENABLE_CONTRAINTS); 
      DbSetup dbSetup = new DbSetup(new DriverManagerDestination("jdbc:mysql://localhost:3306/jukebox", "root", "mpsbart"), operation); 
      dbSetup.launch(); 
      FullTextSession fullTextSession = Search.getFullTextSession(placeDao.getSession()); 
      fullTextSession.createIndexer().startAndWait(); 
    } 

    @Test 
    @Rollback(false) 
    public void searchTest() 
    { 
     PlayList playList = playListDao.read(1l); 
     List<Song> songs = songDao.search(playList, "offspring", 1, 10); 
     assertEquals(10, songs.size()); 
    } 

的搜索方法實現:

@SuppressWarnings("unchecked") 
    public List<Song> search(PlayList playlist, String searchTerm,int page,int limit) 
    { 
     FullTextSession fullTextSession = Search.getFullTextSession(getSession()); 
     QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Song.class).get(); 
     BooleanQuery luceneQuery = new BooleanQuery(); 
     luceneQuery.add(queryBuilder.keyword().onFields("name","album","artist").matching("*"+searchTerm+"*").createQuery(), BooleanClause.Occur.MUST); 
     luceneQuery.add(queryBuilder.phrase().onField("playList.place.id").sentence("\""+playlist.getPlace().getId()+"\"").createQuery(), BooleanClause.Occur.MUST); 
     luceneQuery.add(queryBuilder.phrase().onField("playList.id").sentence("\""+playlist.getId()+"\"").createQuery(), BooleanClause.Occur.MUST); 
     // wrap Lucene query in a javax.persistence.Query 
     FullTextQuery query = fullTextSession.createFullTextQuery(luceneQuery, Song.class); 
     org.apache.lucene.search.Sort sort = new Sort(new SortField("n_votes",SortField.INT)); 
     query.setSort(sort); 
     List<Song> songs = query.setFirstResult(page*limit).setMaxResults(limit).list(); 
     return songs; 
    } 

測試結果失敗,它沒有找到任何匹配的對象。當使用luke lucene時,我可以看到有結果,如果我嘗試在luke上通過休眠生成的查詢,它會返回元素。由Hibernate生成的查詢是:+(名稱:Metallica的專輯:Metallica的藝術家:METALLICA)+ playList.place.id:」 「+ playList.id:」 1"

我也注意到了盧克的Lucene某些索引術語的長度最多可達六個字符,例如,一首歌曲的藝術家是「The Offspring」,索引中存儲的術語是「the」和「offspr」。第一個沒關係,但不應該第二個是「後代」。爲什麼會截斷這個名字?

回答

0

在情況下,它可以幫助任何人,我能夠通過改變查詢此修復它:

 FullTextSession fullTextSession = org.hibernate.search.Search.getFullTextSession(getSession()); 
    QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Song.class).get(); 

    if(searchTerm==null || searchTerm.equals("")) 
     searchTerm="*"; 
    else 
     searchTerm="*"+searchTerm+"*"; 
    Query luceneQuery1 = qb.bool() 
      .should(qb.keyword().wildcard().onField("name").matching(searchTerm).createQuery()) 
      .should(qb.keyword().wildcard().onField("album").matching(searchTerm).createQuery()) 
      .should(qb.keyword().wildcard().onField("artist").matching(searchTerm).createQuery()).createQuery(); 
    Query luceneQuery2 = qb.bool() 
      .must(qb.keyword().wildcard().onField("playList.place.id").matching(playlist.getPlace().getId()).createQuery()) 
      .must(qb.keyword().wildcard().onField("playList.id").matching(playlist.getId()).createQuery()) 
      .createQuery(); 
    BooleanQuery finalLuceneQuery=new BooleanQuery(); 
    finalLuceneQuery.add(luceneQuery1, BooleanClause.Occur.MUST); 
    finalLuceneQuery.add(luceneQuery2, BooleanClause.Occur.MUST); 
    FullTextQuery query = fullTextSession.createFullTextQuery(finalLuceneQuery, Song.class); 
    org.apache.lucene.search.Sort sort = new Sort(new SortField("nvotes",SortField.INT,true)); 
    query.setSort(sort); 
    List<Song> songs = query.setFirstResult(page*limit).setMaxResults(limit).list(); 
0

的情況下,你必須檢查該字段值爲null或不爲空,那麼你必須添加以下行現場,其中類

@Field索引字段(指數= Index.YES,分析= Analyze.NO,存儲= Store.YES,indexNullAs = Field.DEFAULT_NULL_TOKEN)

搜尋現場 如果您(null)value booleanQuery.must(qb.keyword()。onField(「callReminder」)。matching(「null」).createQuery());

如果你不想空值

booleanQuery.must(qb.keyword()。onField( 「callReminder」)。匹配( 「」).createQuery())。不是() ;

參考文獻:http://docs.jboss.org/hibernate/search/4.1/reference/en-US/html/search-mapping.html#search-mapping-entity