DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Stefan has posted 2 posts at DZone. View Full User Profile

Compass: Fetching Distinct Property Values

06.02.2009
| 3121 views |
  • submit to reddit
        fetching only distinct (unique) property values using CompassTemplate

/**
 * get list of unique values for a single property
 * 
 * @param type
 *            the searchable
 * @param name
 *            name of the property to fetch unique values for
 * @param query
 *            the query (it's not limited to the property you fetch)
 * @param count
 *            max amount of results
 * @return a sorted list of strings for this property
 */
public List<String> getProperty(final Class<? extends IPersistentObject> type, final String name, final String query, final int count) {
	return getCompassTemplate().execute(new CompassCallback<List<String>>() {

		@Override
		public List<String> doInCompass(final CompassSession session) throws CompassException {
			try {
				final ResourceMapping mapping = ((InternalCompassSession) session).getMapping()
						.findRootMappingByClass(type);
				final LuceneSearchEngineInternalSearch lucene = LuceneHelper
						.getLuceneInternalSearch(session, mapping.getSubIndexHash()
								.getSubIndexes(), new String[] { mapping.getAlias() });

				final CompassQueryBuilder build = session.queryBuilder();
				final CompassQuery q = build.queryString(query).toQuery();

				final UniqueValuesCollector uniqueValues = new UniqueValuesCollector(name, lucene
						.getReader());

				lucene.getSearcher()
						.search(((LuceneSearchEngineQuery) ((DefaultCompassQuery) q)
								.getSearchEngineQuery()).getQuery(), uniqueValues);

				return uniqueValues.getValues(count);
			} catch (final IOException e) {
				throw new CompassException("failed to get terms from reader", e);
			}

		}

	});
}

/*
 * collect unique values of a single proprty
 */
private final class UniqueValuesCollector extends HitCollector {
	private final String _name;
	private final Set<String> _values = new TreeSet<String>();
	private final IndexReader _reader;

	private UniqueValuesCollector(final String name, final IndexReader indexReader) {
		_name = name;
		_reader = indexReader;
	}

	@Override
	public void collect(final int docId, final float score) {
		try {
			final Document doc = _reader.document(docId);
			if (doc != null) {
				final String value = doc.get(_name);
				if (value != null && !"".equals(value)) {
					_values.add(value);
				}
			}
		} catch (final SearchEngineException e) {
			log.warn("failed to collect unique values for " + _name, e);
		} catch (final CorruptIndexException e) {
			log.warn("failed to collect unique values for " + _name, e);
		} catch (final IOException e) {
			log.warn("failed to collect unique values for " + _name, e);
		}
	}

	public List<String> getValues(int max) {
		max = Math.min(max, _values.size());
		final ArrayList<String> values = new ArrayList<String>(max);

		final Iterator<String> iter = _values.iterator();
		while (values.size() < max && iter.hasNext()) {
			values.add(iter.next());
		}	
		return values;
	}
}