0
votes

This is my Mongo Pojo also getters and setters(Not added) .

    @CompoundIndex(name = "account_date_idx", def = "{'account' : 1, 'date' : 1}", unique = true)
@Document(collection = "agent_data_storage")
public class AgentDataStorage extends MongoKeyedEntity<String> implements Serializable {

  public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
  @Field
  private Long account;

  @Field()
  private String date;

  @Field
  private Map<String, Double> dataPoints = new HashMap<>();

  public AgentDataStorage() {
  }

  public AgentDataStorage(Long account) {
    this.account = account;
    this.date = dateFormat.format(new Date());
    for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
      this.dataPoints.put(dataPoint.toString(), 0d);
    }
  }

  public AgentDataStorage(String account) {
    this.account = Long.valueOf(account);
    for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
      this.dataPoints.put(dataPoint.toString(), 0d);
    }
  }

  public AgentDataStorage(Long account, Date date) {
    this.account = account;
    this.date = dateFormat.format(date);
    for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
      this.dataPoints.put(dataPoint.toString(), 0d);
    }
  }

  public AgentDataStorage(Long account, Date date, Map<String, Double> dataPoints) {
    this.account = account;
    this.date = dateFormat.format(date);
    this.dataPoints = dataPoints;
  }

  public AgentDataStorage(Long account, String date, Map<String, Double> dataPoints) {
    this.account = account;
    this.date = date;
    this.dataPoints = dataPoints;
  }

  public AgentDataStorage(String account, Date date) {
    this.account = Long.valueOf(account);
    this.date = dateFormat.format(date);
    for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
      this.dataPoints.put(dataPoint.toString(), 0d);
    }
  }

  public AgentDataStorage(String account, String date) {
    this.account = Long.valueOf(account);
    this.date = date;
    for (AgentDataPoints dataPoint : EnumSet.allOf(AgentDataPoints.class)) {
      this.dataPoints.put(dataPoint.toString(), 0d);
    }
  }

  public Long getAccount() {
    return account;
  }

  public void setAccount(Long account) {
    this.account = account;
  }

  public Date getDate() throws ParseException {
    return dateFormat.parse(this.date);
  }

  public void setDate(Date date) {
    this.date = dateFormat.format(date);
  }

  public Map<String, Double> getDataPoints() {
    return dataPoints;
  }

  public void setDataPoints(Map<String, Double> dataPoints) {
    this.dataPoints = dataPoints;
  }

  public void updateDataPoint(AgentDataPoints agentDataPoints, Double value) {
    this.dataPoints.put(String.valueOf(agentDataPoints), value);
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder("AgentDataStorage{");
    sb.append("account=").append(account);
    sb.append(", date=").append(date);
    sb.append(", dataPoints=").append(dataPoints);
    sb.append('}');
    return sb.toString();
  }
}

While Trying aggregation i am getting null Pointer Exception , Below is my Test Case.

     @Test
  public void aggregationTest() {
    Long account = 12121l;
    String startDay = "2016-01-01";
    String endDay = "2016-01-03";

    Aggregation aggregation = Aggregation
        .newAggregation(match(Criteria.where("account").is(account).and("date")
            .gte(startDay).lte(endDay)),
            group("account").sum("dataPoints.TOTAL_BUS_COMMISSION").as("total"));
    AggregationResults<AggregationResult> results = mongoTemplate.aggregate(aggregation,
        AgentDataStorage.class, AggregationResult.class);

  }

My AggregationResult class is -

public class AggregationResult {

  private Long _id;

  private Double total;

  public Long get_id() {
    return _id;
  }

  public void set_id(Long _id) {
    this._id = _id;
  }

  public Double getTotal() {
    return total;
  }

  public void setTotal(Double total) {
    this.total = total;
  }
}

Below is Stack Trace Of Error

java.lang.NullPointerException
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:233)
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:214)
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:210)
    at org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext.getReferenceFor(TypeBasedAggregationOperationContext.java:96)
    at org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext.getReference(TypeBasedAggregationOperationContext.java:91)
    at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.getValue(GroupOperation.java:434)
    at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.toDBObject(GroupOperation.java:416)
    at org.springframework.data.mongodb.core.aggregation.GroupOperation.toDBObject(GroupOperation.java:361)
    at org.springframework.data.mongodb.core.aggregation.Aggregation.toDbObject(Aggregation.java:331)
    at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1500)
    at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1435)
    at psl.service.core.agentanalytics.internal.AgentAnalyticsServiceTest.aggregationTest(AgentAnalyticsServiceTest.java:132)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:72)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:81)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:216)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:82)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:60)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:67)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:162)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)

I also tried to debug the inside spring jar , It's throwing null for Double type inside AbstractMappingContext.java but not able to understant why it's happening . The same mongo query is working in mongo console.

db.getCollection('agent_data_storage').aggregate([ 
{ "$match" : { "account" : 12121 , "date" : { "$gte" : "2016-01-01" , "$lte" : "2016-01-03"}}} 
, { "$group" : { "_id" : "$account" , "total" : { "$sum" : "$dataPoints.TOTAL_BUS_COMMISSION"}}}])

the result for the above query is

 {
    "_id" : NumberLong(12121),
    "total" : 402.0
}

Thanks for any kind of Help .

Sample Doc from AgentDataStorage-

{
    "_id" : ObjectId("586233e3fb94f6f5640196cf"),
    "account" : NumberLong(12121),
    "date" : "2016-01-01",
    "dataPoints" : {
        "TOTAL_BUS_COMMISSION" : 0.0
    }
}
1

1 Answers

2
votes

Don't use the typed aggregation variant of aggregation which is essentially trying to translate property references in the input type (AgentDataStorage) into field names and fails when it doesn't find the property references, in your case dataPoints.TOTAL_BUS_COMMISSION.

Use

AggregationResults<AggregationResult> results = mongoTemplate.aggregate(aggregation,
    "agent_data_storage", AggregationResult.class);