Carlos Jaime C. De Leon Carlos Jaime C. De Leon - 3 months ago 32
Java Question

MarkLogic PojoRepository search range Dates not working

My query:

PojoQueryBuilder<CaseComment> queryBuilder = pojoRepository.getQueryBuilder();
LocalDateTime plusHours = LocalDateTime.now().plusHours(hours); //hours is -24
Date from = Date.from(plusHours.atZone(ZoneId.systemDefault()).toInstant());

PojoQueryDefinition query =
queryBuilder.filteredQuery(
queryBuilder.range("createdDate", Operator.GT, from)
);

PojoPage<CaseComment> results = pojoRepository.search(query,1);


However, this is returning me all comments (24 records) and not the comments that were made in the past 24 hours, which should just be 3 records. I've already added the RangePathIndex (as dateTime) and the date format is defaulted to the PojoRepository's ObjectMapper.

See this sample JSON (notice the dateformat is default ISO):

{
"com.xxx.domain.CaseComment": {
"id": 164,
"createdDate": {
"java.util.Date": "2016-07-27T22:49:00.000Z"
},
"createdBy": "xxx",
"updatedDate": {
"java.util.Date": "2016-07-27T22:49:00.000Z"
},
"updatedBy": "xxx",
"description": "comment",
"caseId": 69
}
}


Please help, I've lost the whole day already and cannot seem to find the issue?

Answer

In my opinion, you have found a bug. What you're doing strikes me as the right things to do, but the PojoQueryBuilder implementation doesn't support that, as you have found. As you can see, PojoRepository takes special care to serialize your java.util.Date instances in ISO 8601 format so they can be indexed as a MarkLogic range index. So that piece is good. But the two problems are 1) your dates have a nested object with the key "java.util.Date" which prevents you from creating a path range index to match your query on "createdDate". Here your path range index would need to be "com.macquarie.rmg.dawn.casemanager.domain.CaseComment/createdDate/java.util.Date" but your query would be just "com.macquarie.rmg.dawn.casemanager.domain.CaseComment/createdDate".

I've logged the bug and we'll get it fixed right away. In the mean-time, here are two work-arounds:

  1. use numeric date values and a numeric range index
  2. use Jackson annotations to remove the nested "java.util.Date" object and override the Date.toString method on your "from" instance so it serializes in ISO 8601 format.

Hopefully the first work-around is straight-forward and doesn't require a detailed explanation. I'll demonstrate the second work-around.

Date from = new java.util.Date() {
  public String toString() {
    return DatatypeConverter.printDateTime(Calendar.getInstance());
  }
};

PojoQueryDefinition query =
    queryBuilder.filteredQuery(
            queryBuilder.range("createdDate", Operator.GT, from)
    );

PojoPage<CaseComment> results = pojoRepository.search(query,1);

Then on your com.macquarie.rmg.dawn.casemanager.domain.CaseComment.getCreatedDate method you'll need to add the JsonTypeInfo jackson annotation so it can serialize without the nested "java.util.Date" object:

public CaseComent {
  // ...

  @JsonTypeInfo(use=JsonTypeInfo.Id.NONE, include=JsonTypeInfo.As.EXTERNAL_PROPERTY)
  public Date getCreatedDate() {
    // ...
  }
}
Comments