Is there a way to create an Index with @Index on the key of a map?
Indexes on map keys as well as queries on map keys are currently not supported.
But as a workaround you can use a collection of embedded objects, as demonstrated below:
package test;
import java.util.*;
import javax.jdo.annotations.Index;
import javax.persistence.*;
public class T1255 {
public static void main(String[] args) {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(
"objectdb:test.tmp;drop");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
for (int i = 0; i < 100000; i++) {
MyEntry entry = new MyEntry("k" + i, "v" + i);
em.persist(new MyEntity(Collections.singletonList(entry)));
}
em.getTransaction().commit();
em.close();
em = emf.createEntityManager();
long ms = System.currentTimeMillis();
Query query = em.createQuery(
"SELECT o FROM MyEntity o JOIN o.map e WHERE e.key = 'k50000'");
List resultList = query.getResultList();
ms = System.currentTimeMillis() - ms;
System.out.println("Result: " + resultList);
System.out.println("Time: " + ms + "ms");
em.close();
emf.close();
}
@Entity
@Index(members={"map.key"})
public static class MyEntity {
MyEntity(Collection<MyEntry> map) {
this.map = map;
}
Collection<MyEntry> map;
@Override
public String toString() {
return map.toString();
}
}
@Embeddable
public static class MyEntry {
String key;
String value;
public MyEntry(String key, String value) {
this.key = key;
this.value = value;
}
@Override
public String toString() {
return key + ":" + value;
}
}
}
In this example, the field map is implemented as Collection<MyEntry>, i.e. a collection of a key-value embeddable objects.
An index on the key is defined using @Index(members={"map.key"}).
Running this example with and without the index definition shows that performance with index is better.