Hello,
I'm having some issues with using filters in Hibernate Search.
My idea is to have a query be run then have the filter applied after the initial search and perform some filtering (as is the idea behind filters I guess ;)
My issue is when the query is run and the logic moves into the filter, I'm not sure I'm getting the results from the initial query or all docs from the index. I question this as I've noticed debugging that some docs that are in the filter shouldn't be returned from the initial query.
As well as this, with some simple logging I've noticed that the filter is actually being looped through 5 times. In the code below, in the filter the line
Code:
log.debug("Bit Set before Filter size [" + bits.size() + "]");
is run 5 times as the messages appears in my log file. Once the 5th time is logged, the logic moves out of the filter.
Can I get some help on this please. Below is extracts of code including the model being searched for with Filter Defs, the Hibernate Search object which initiates the search including enabling the filters, the Filter Factory and the Filter itself. I've tried to remove code that is business logic to make it clearer.
I'm using Hibernate Search 3.1.1.GA release, including the Lucene 2.4.1 release jars.
Thanks,
Christian
Media Model with FullTextFilterDefs
Code:
@FullTextFilterDefs( {
@FullTextFilterDef(name = "mediaTypeFilter", impl = MediaTypeFilterFactory.class),
@FullTextFilterDef(name = "activeStatusFilter", impl = ActiveStatusFilterFactory.class),
@FullTextFilterDef(name = "mediaScheduleFilter", impl = MediaSchedulesFilterFactory.class, cache = FilterCacheModeType.NONE)})
public class Media implements Serializable {
...
}
Hibernate Search object
Code:
Session session = HibernateUtils.currentSession();
FullTextSession fullTextSession = Search.getFullTextSession(session);
try {
FullTextQuery fullTextQuery = null;
fullTextQuery = fullTextSession.createFullTextQuery(
queryBuilder.parseQuery(fullTextSession), queryBuilder.getEntityClass())
.setFirstResult(offset)
.setMaxResults(limit);
queryBuilder.loadFilters(fullTextQuery);
List<T> results = (List<T>) fullTextQuery
.setCacheable(true)
.list();
queryBuilder.unloadFilters(fullTextQuery);
return results;
} catch (Exception e) {
...
}
Query Builder Object
Code:
public void loadFilters(FullTextQuery fullTextQuery) {
if (mediaType != null) {
fullTextQuery.enableFullTextFilter("mediaTypeFilter").setParameter("mediaType", mediaType);
}
fullTextQuery.enableFullTextFilter("mediaScheduleFilter")
.setParameter("session", session)
.setParameter("userDate", userDate);
}
Filter Factory
Code:
public class MediaSchedulesFilterFactory {
private Session session;
private Date userDate;
@Key
public FilterKey getKey() {
StandardFilterKey key = new StandardFilterKey();
key.addParameter(session);
key.addParameter(userDate);
return key;
}
@Factory
public Filter getFilter() {
Filter mediaSchedulesFilter = new MediaSchedulesFilter(session, userDate);
return mediaSchedulesFilter;
}
public void setSession(Session session) {
this.session = session;
}
public void setUserDate(Date userDate) {
this.userDate = userDate;
}
}
Filter object
Code:
public class MediaSchedulesFilter extends Filter {
private static final long serialVersionUID = 1L;
public static Log log = LogFactory.getLog(MediaSchedulesFilter.class);
private Session session;
private Date userDate;
public MediaSchedulesFilter(Session session, Date userDate) {
super();
this.session = session;
this.userDate = userDate;
}
@Override
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
BitSet bits = getBitSet(reader.maxDoc());
log.debug("Bit Set before Filter size [" + bits.size() + "]");
Term msTerm = new Term(DocumentBuilder.CLASS_FIELDNAME, Media.class.getName());
TermDocs td = reader.termDocs(msTerm);
while(td.next()) {
Document termDoc = reader.document(td.doc());
Field termDocMediaSchedule = termDoc.getField("mediaSchedules");
String termDocMediaScheduleValue = termDocMediaSchedule.stringValue();
if(termDocMediaScheduleValue != null && !termDocMediaScheduleValue.isEmpty()) {
boolean valid = // Logic to determine is valid to be returned in search results
if(valid) {
bits.set(td.doc());
}
}
}
log.debug("Bit Set after Filter size [" + bits.size() + "]");
DocIdSet docIdSet = new DocIdBitSet( bits );
return docIdSet;
}
private BitSet getBitSet(int maxDoc) {
BitSet bitSet = new BitSet( maxDoc );
return bitSet;
}
}
Hopefully this is enough information. If more is required please let me know.
Regards,
Christian