I use ehcache (2.10.6) with DynamicAttributeExtractor to be able to search through the cache elements by their fields. Doc says that the DynamicAttributeExtractor will be called once per each put() and replace() method call, and ehcache will index returned attribute values, so I expect that when I will execute a query by some of the attributes produced by this extractor, ehcache will use that attribute index and will quickly return matched elements without iterating over all cache items.
When I test that, I see that my extractor is expectedly called on each put() method call and return required attribute value, but then, when I execute the query by this attribute, I see that the extractor is called again and again for each next query.
My cache configuration in ehcache.xml
<ehcache ...>
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
memoryStoreEvictionPolicy="LRU">
<pinning store="inCache" />
<persistence strategy="localTempSwap"/>
</defaultCache>
<cache name="users"
maxBytesLocalHeap="1G"
eternal="false"
timeToLiveSeconds="43200"
memoryStoreEvictionPolicy="LRU">
<pinning store="inCache" />
<persistence strategy="none"/>
<searchable keys="true" values="false" allowDynamicIndexing="true"/>
</cache>
</ehcache>
The code snippet I use to search in ehcache by attribute:
private static final String FULL_NAME_ATTR = "fullName";
public static void main(String[] args) {
final CacheManager cacheManager = CacheManager.newInstance(".../ehcache.xml");
final Cache users = cacheManager.getCache("users");
// register extractor that will extract user's full name into attribute 'fullName'
users.registerDynamicAttributesExtractor(new DynamicAttributesExtractor() {
@Override
public Map<String, Object> attributesFor(Element element) {
final Map<String, Object> attrs = new HashMap<>();
final User user = (User) element.getObjectValue();
attrs.put(FULL_NAME_ATTR, user.getFirstName() + " " + user.getLastName());
return attrs;
}
});
// fill the cache; the extractor is called on each put() call
users.put(new Element(1, new User("John", "Doe")));
users.put(new Element(2, new User("user1", "user1")));
users.put(new Element(3, new User("user2", "user2")));
users.put(new Element(4, new User("user3", "user3")));
// find John Doe, the extractor is called again, why?
// Didn't it already extract this attribute when John Doe has been put into cache?
findByFullName("John Doe", users).forEach(result -> System.out.println(result.getValue()));
// and again...
findByFullName("John Doe", users).forEach(result -> System.out.println(result.getValue()));
}
private static List<Result> findByFullName(String fullName, Cache cache) {
return cache.createQuery()
.addCriteria(cache.getSearchAttribute(FULL_NAME_ATTR).eq(fullName))
.includeValues()
.execute()
.all();
}
Do I understand the meaning of "DynamicAttributeExtractor indexes attribute values" correctly? If so, why the extractor is called when the element enters into the cache, but extracted attribute value is not used by ehcache in any way?
Such querying has terrible performance since each time it is an iteration over all the elements of the cache without any indexing at all.