3.6 Group Aggregation Question
I am trying to achieve a sql group by sort of behavior with coherence 3.6. I have achieved some success by using the following code.
public InvocableMap.EntryAggregator getAggregationCriteria()
{
BigDecimalSum agg1 = new BigDecimalSum("getTradeDateMVLocal");
BigDecimalSum agg2 = new BigDecimalSum("getTradeDateCashLocal");
BigDecimalSum agg3 = new BigDecimalSum("getCostLocal");
BigDecimalSum agg4 = new BigDecimalSum("getInterestUnrealizedLocal");
CompositeAggregator compAgg =
CompositeAggregator.createInstance(new InvocableMap.EntryAggregator[]
{agg1, agg2, agg3, agg4});
ChainedExtractor cr1 = new ChainedExtractor("getKey.getAccountName");
ChainedExtractor cr2 = new ChainedExtractor("getKey.getCurrency");
ValueExtractor[] extractors = new ValueExtractor[2];
extractors[0] = cr1;
extractors[1] = cr2;
MultiExtractor multiEx = new MultiExtractor(extractors);
GroupAggregator gpa = GroupAggregator.createInstance(multiEx, compAgg);
return gpa;
}
once the GroupAggregator is constructed I pass it to the namedcache.aggregate method using the following wrapper method.
public LiteMap aggregate(NamedCache cache, Filter filter, InvocableMap.EntryAggregator aggregationCriteria)
{
LiteMap map = (LiteMap) cache.aggregate(filter, aggregationCriteria);
return map;
}
the issue is that in a multi-node environment not all the data is aggregated.
for example if i have a single node and i run my aggregation code just in that node i get the expected number of grouped items. in a multi node scenario it ends up with lesser items. now the columns that i am grouping by are part of my composite key for the cache. the implementation of my key class is as follows.
package com.sac.dream.model;
import com.sac.dream.core.model.GridEntityKey;
import com.sac.dream.util.externalization.ObjectReader;
import com.sac.dream.util.externalization.ObjectWriter;
import com.tangosol.net.cache.KeyAssociation;
import javax.persistence.Embeddable;
import javax.persistence.Transient;
import java.io.IOException;
/**
* Created by IntelliJ IDEA.
* User: ahmads
* Date: Jul 28, 2010
* Time: 1:54:45 PM
* To change this template use File | Settings | File Templates.
*/
@Embeddable
public class GenevaValuationKey extends GridEntityKey implements KeyAssociation
{
private static final long serialVersionUID = 1L;
private String accountName;
private String currency;
private Long uid;
public GenevaValuationKey(Long uid)
{
this.uid = uid;
}
public GenevaValuationKey()
{
}
@Transient
public Object getAssociatedKey()
{
int hash = 1;
hash = hash * 31 + getAccountName().hashCode();
hash = hash * 31 + getCurrency().hashCode();
return hash;
}
public void setAssociatedKey(Object value)
{}
public Long getUid() {
return uid;
}
public void setUid(Long uid) {
this.uid = uid;
}
@Override
public String toString()
{
return "GenevaValuationKey::uid:" + this.uid;
}
@Override
public boolean equals(Object o)
{
//if(this == o) return true;
//if (o == null || getClass() != o.getClass()) return false;
GenevaValuationKey that = (GenevaValuationKey) o;
if(this.getAccountName().equals(that.getAccountName()) && this.getCurrency().equals(that.getCurrency()) && this.uid == that.uid)
{
return true;
}
else
return false;
}
@Override
public int hashCode()
{
int hash = 1;
hash = hash * 31 + getAccountName().hashCode();
hash = hash * 31 + getCurrency().hashCode();
hash = hash * 31 + uid.hashCode();
return hash;
}
@Override
public int compareTo(GridEntityKey o)
{
return this.uid.compareTo(((GenevaValuationKey) o).getUid());
}
@Override
public final void readObject(ObjectReader reader) throws IOException
{
try
{
this.setAccountName(reader.readString());
this.setCurrency(reader.readString());
this.uid = reader.readLong();
}
catch(IOException e)
{
throw new RuntimeException(e);
}
}
@Override
public final void writeObject(ObjectWriter writer) throws IOException
{
try
{
writer.writeString(this.getAccountName());
writer.writeString(this.getCurrency());
writer.writeLong(this.uid);
}
catch(IOException e)
{
throw new RuntimeException(e);
}
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
}
i implemented the keyassociation assuming that i need to make sure that for a certain group all the rows within that group need to exist on the same node. there might be something wrong with that implementation.
thanks