5

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.

Pavel Niedoba
  • 1,554
  • 2
  • 19
  • 36

4 Answers4

1

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;
Pavel Niedoba
  • 1,554
  • 2
  • 19
  • 36
1

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).

npgall
  • 2,979
  • 1
  • 24
  • 24
0

or iterator of the index in general

You can use getIndexes() API of QueryEngine interface to retrieve set of Indexes.

Example code:

IndexedCollection<Car> indexedCollection = new ConcurrentIndexedCollection<Car>();
indexedCollection.addIndex(HashIndex.onAttribute(Car.CAR_ID), noQueryOptions());

List<Index<Car>> indexes = new ArrayList<Index<Car>>();
for (Index<Car> index : indexedCollection.getIndexes()) {
    indexes.add(index);
}
miradham
  • 2,285
  • 16
  • 26
-1

NavigableIndex stores object in element in Map with attribute as key and set of object as value.

NavigableIndex does not maintain insertion order. First element of the index could be anything.

CQEngine is best designed for random access of object in collection not sequential.

Normal collections in java is best suited for sequence access with index.

one elegant way of accessing first element is to create SequentialIndex class and add it to concurrent collection. retrieve element using index as query.

  • Index maintain order given by comparator, so the first cannot be anything but the smallest one. I cannot find SequentialIndex in CQEngine library. – Pavel Niedoba Jul 24 '18 at 16:48