【问题标题】:Hibernate Search not returning results休眠搜索不返回结果
【发布时间】:2014-06-15 22:49:54
【问题描述】:

我正在使用 Hibernate Search 4.5.1 和 Spring 4.0.5.RELEASE 构建一个应用程序。我正在尝试索引以下类:

@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 生成的查询,它确实会返回元素。 hibernate生成的查询是:+(name:metallica album:metallica artist:metallica) +playList.place.id:"1" +playList.id:"1"

我还在 luke lucene 上注意到一些索引词的长度最多为六个字符,例如,一首歌的艺术家是“The Offspring”,而存储在索引中的词是“the”和“offspr”。第一个没关系,但第二个词不应该是“后代”。为什么要截断名称?

【问题讨论】:

    标签: spring lucene hibernate-search


    【解决方案1】:

    如果它对任何人有帮助,我可以通过将查询更改为以下方式来修复它:

            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();
    

    【讨论】:

      【解决方案2】:

      如果您检查了字段值是否为空,那么您必须在类中索引字段的字段上添加以下行

      @Field(index=Index.YES,analyze=Analyze.NO,store=Store.YES,indexNullAs=Field.DEFAULT_NULL_TOKEN)

      在字段上搜索 如果你想要空值那么 booleanQuery.must(qb.keyword().onField("callReminder").matching("null").createQuery());

      如果你不想要空值

      booleanQuery.must(qb.keyword().onField("callReminder").matching("null").createQuery()).not();

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多