Reputation: 455
Is there a simple way to apply the following filter query:
userAccessibleDocTypesSet.contains(doc.type)
where the set is passed to the query (with scattered integers), and doc.type is a stored int field on the documents. A BooleanQuery with a should-clause for all values in the set seems overkill, and might push the limits.
What would be the right approach? How to apply this filter last, for the case when it doesn't filter anything due to full access rights for the user?
Upvotes: 1
Views: 542
Reputation: 455
This is what I came up with. If you see any performance concerns, please let me know.
public class FilterByIntegerSetQuery extends Query
{
protected String numericDocValueFieldName;
protected Set<Integer> allowedValues;
public FilterByIntegerSetQuery(String numericDocValueFieldName, Set<Integer> allowedValues)
{
this.numericDocValueFieldName = numericDocValueFieldName;
this.allowedValues = allowedValues;
}
@Override
public Weight createWeight(IndexSearcher searcher, boolean needsScores)
{
return new RandomAccessWeight(this)
{
@Override
protected Bits getMatchingDocs(LeafReaderContext context) throws IOException
{
final int len = context.reader().maxDoc();
final NumericDocValues values = context.reader().getNumericDocValues(numericDocValueFieldName);
return new Bits()
{
@Override
public boolean get(int index)
{
return allowedValues.contains((int) values.get(index));
}
@Override
public int length()
{
return len;
}
};
}
};
}
@Override
public String toString(String field)
{
return "(filter "+numericDocValueFieldName+" by set)";
}
}
Upvotes: 1