Daniel Jipa
Daniel Jipa

Reputation: 888

Hibernate search too many results

I want to return records from database using hibernate search. I have difficulties when the search string is actually a phrase, otherwise things looks OK. I have several fields on which I make the search and I do not know runtime on which field I should make the query so I made a BooleanJunction and used the should DSL method like this:

final Query spatialLuceneQuery = queryBuilder.spatial().within(200, Unit.KM).ofLatitude(latitude)
            .andLongitude(longitude).createQuery();
bool.must(spatialLuceneQuery);

if (tag != null) {
    if (isPhrase(tag.getTag())) {
        final Query phraseTagsLuceneQuery = queryBuilder.phrase().withSlop(2).onField("tags").sentence(tag.getTag()).createQuery();
        final Query phraseNameLuceneQuery = queryBuilder.phrase().onField("name").sentence(tag.getTag()).createQuery();
        final Query phraseDescriptionLuceneQuery = queryBuilder.phrase().withSlop(3).onField("description").sentence(tag.getTag()).createQuery();
        final Query phraseActiveSkillsLuceneQuery = queryBuilder.phrase().withSlop(1).onField("activeSkills").sentence(tag.getTag()).createQuery();
        bool.should(phraseTagsLuceneQuery).should(phraseActiveSkillsLuceneQuery).should(phraseNameLuceneQuery).should(phraseDescriptionLuceneQuery);
    } else {
        final Query fuzzyLuceneQuery = queryBuilder.keyword().fuzzy().withEditDistanceUpTo(2).withPrefixLength(1).onFields("tags", "activeSkills","name","description").matching(tag.getTag()).createQuery();
        bool.must(fuzzyLuceneQuery);
    }
}

When the isPhrase method returns true all the records in the table are returned. How can I restrict the results to the relevant ones?

Mapping looks like this:

@Entity
@Table(name = "USER_INDEXED_SEARCH")
@Indexed
@Spatial(spatialMode = SpatialMode.RANGE)
@AnalyzerDef(name = "customAnalyzer", tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class) , filters = {
    @TokenFilterDef(factory = LowerCaseFilterFactory.class),
    @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class),
    @TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = {
            @Parameter(name = "language", value = "Romanian") }) })
public class UserIndexedSearch extends DefaultLoggable {

private static final long serialVersionUID = -8021827814963060426L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@DocumentId
@Column(name = "USER_INDEXED_SEARCH_ID")
private Integer userIndexSearchId;

@Latitude
@Column(name = "LATITUDE")
private Double lat;

@Longitude
@Column(name = "LONGITUDE")
private Double lon;

@Column(name = "USER_ID")
private Integer userId;

@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
@Analyzer(definition = "customAnalyzer")
@Column(name = "TAGS")
private String tags;

@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
@Analyzer(definition = "customAnalyzer")
@Column(name = "ACTIVE_AREAS")
private String activeAreas;

@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
@Analyzer(definition = "customAnalyzer")
@Column(name = "ACTIVE_SKILLS")
private String activeSkills;

@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
@Analyzer(definition = "customAnalyzer")
@Column(name = "NAME")
private String name;

@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
@Analyzer(definition = "customAnalyzer")
@Column(name = "DESCRIPTION")
private String description;

Thank you!

Upvotes: 1

Views: 740

Answers (1)

Atul Kumar
Atul Kumar

Reputation: 749

When You will find yourself sometimes puzzled by a result showing up in a query or a result not showing up in a query.Hibernate Search gives you access to the Lucene Explanation object for a given result (in a given query). This class is considered fairly advanced to Lucene users but can provide a good understanding of the scoring of an object. You have two ways to access the Explanation object for a given result:

  • Use the fullTextQuery.explain(int) method
  • Use projection

Example using projection:

FullTextQuery ftQuery = s.createFullTextQuery( luceneQuery, Dvd.class )
        .setProjection( FullTextQuery.DOCUMENT_ID, FullTextQuery.EXPLANATION, FullTextQuery.THIS );
@SuppressWarnings("unchecked") List<Object[]> results = ftQuery.list();
for (Object[] result : results) {
    Explanation e = (Explanation) result[1];
    display( e.toString() );
}

Upvotes: 1

Related Questions