Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get first or last item from cqengine IndexedCollection with NavigableIndex

Tags:

java

cqengine

I have com.googlecode.cqengine.IndexedCollection object with NavigableIndex configured. I need to get first or last item from the index or iterator of the index in general.

I suppose this should be trivial. I know I can create Query object with queryOptions object, use it to retrieve iterator from IndexedCollection and get first object, but I'm not sure if it's optimal for performance. Surely it's not elegant.

like image 791
Pavel Niedoba Avatar asked Nov 08 '22 04:11

Pavel Niedoba


2 Answers

With help of miradham I figured out that I need to remember indexes, since it's hard to pick up the right one if we have more of them. It will only work with NavigableIndex, we can't iterate base class Index

collection = new ConcurrentIndexedCollection<Data>();
index = NavigableIndex.onAttribute(Data.UNIQUE_TIMESTAMP);
collection.addIndex(index);

when I have the index:

try (CloseableIterator<KeyValue<String, Data>> iterator = indexUniqueTimestamp.getKeysAndValuesDescending(null).iterator()) {
        if (iterator.hasNext())
            return iterator.next().getValue();
    }
    return null;
like image 140
Pavel Niedoba Avatar answered Dec 09 '22 08:12

Pavel Niedoba


One trick to retrieve the min or max (i.e first or last) object according on one of its attributes, is to use an all() query (which matches all objects in the collection), and to request that results should be returned in ascending or descending order of your attribute.

For example, if you had a collection of Car objects, you could use the following code to retrieve the car which has the highest (i.e. the max) price:

try (ResultSet<Car> results = cars.retrieve(
    all(Car.class),
    queryOptions(
        orderBy(descending(Car.PRICE)),
        applyThresholds(
            threshold(INDEX_ORDERING_SELECTIVITY, 1.0)
        )
    ))) {

    results.stream()
        .limit(1)
        .forEach(System.out::println);
}

You can also change the limit to something other than 1, in case you want the top n most expensive cars to be returned.

The code above will work regardless of whether or not you actually have a NavigableIndex on the price. The bit about INDEX_ORDERING_SELECTIVITY is to actually request CQEngine to leverage the index (more details here).

like image 38
npgall Avatar answered Dec 09 '22 08:12

npgall