下面列出了怎么用org.elasticsearch.search.aggregations.Aggregations的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
Aggregations aggregations = response.getAggregations();
Terms agg = aggregations.get(term) ;
long total = agg.getSumOfOtherDocCounts() ;
List<T> results = new ArrayList<T>();
if(agg.getBuckets()!=null && agg.getBuckets().size()>0){
for (int i = pageable.getPageNumber()*pageable.getPageSize();i<agg.getBuckets().size() ; i++) {
Terms.Bucket entry = agg.getBuckets().get(i) ;
if(!StringUtils.isBlank(name) && entry.getAggregations().get(name)!=null){
TopHits topHits = entry.getAggregations().get(name);
for (SearchHit hit : topHits.getHits().getHits()) {
T data = mapEntity(hit.getSourceAsString() , hit , clazz) ;
if(data instanceof UKAgg){
((UKAgg) data).setRowcount((int) topHits.getHits().getTotalHits());
}
results.add(data) ;
}
}
}
}
return new AggregatedPageImpl<T>(results, pageable, total);
}
protected synchronized void loadValueStats() {
if (stats != null) {
return;
}
// TODO join userQueryBuilder and itemQueryBuilder
final SearchResponse response = client
.prepareSearch(preferenceIndex)
.setTypes(preferenceType)
.setQuery(getLastAccessedFilterQuery())
.setSize(0)
.addAggregation(
AggregationBuilders.stats(valueField).field(valueField))
.execute().actionGet();
final Aggregations aggregations = response.getAggregations();
stats = aggregations.get(valueField);
}
/**
* 赋值天趋势统计
*/
private void setStatDate(Map<String, Object> result, Aggregations aggregations) {
ParsedDateHistogram agg = aggregations.get("statDate");
List<String> items = new ArrayList<>();
List<Long> uv = new ArrayList<>();
List<Long> pv = new ArrayList<>();
Cardinality cardinality;
for (Histogram.Bucket bucket : agg.getBuckets()) {
items.add(getTimeByDatetimeStr(bucket.getKeyAsString()));
pv.add(bucket.getDocCount());
cardinality = bucket.getAggregations().get("uv");
uv.add(cardinality.getValue());
}
result.put("statDate_items", items);
result.put("statDate_uv", uv);
result.put("statDate_pv", pv);
}
private void parseAggregations(Aggregations aggregations, Map<String, Object> aggMap, String parent) {
for (Aggregation aggregation : aggregations) {
if (aggregation instanceof ParsedNested) {
parseNestedAggregation(aggregation, aggMap);
} else if (aggregation instanceof ParsedComposite) {
parseCompositeAggregation(aggregation, aggMap, parent);
} else if (aggregation instanceof ParsedTerms) {
parseTermsAggregation(aggregation, aggMap, parent);
} else if (aggregation instanceof ParsedTopHits) {
parseTopHitsAggregation(aggregation, aggMap);
} else if (aggregation instanceof ParsedCardinality) {
parseCardinalityAggregation(aggregation, aggMap);
} else if (aggregation instanceof ParsedRange) {
parseRangeAggregation(aggregation, aggMap);
} else if (aggregation instanceof ParsedGeoBounds) {
parseGeoBoundAggregation(aggregation, aggMap);
}
}
}
public static void main(String[] args) throws IOException {
RestHighLevelClient client = HighLevelClient.getInstance();
try{
ChildrenAggregationBuilder aggregationBuilder = new ChildrenAggregationBuilder("utm","histogram");
aggregationBuilder.field("utm");
SearchRequest searchRequest = new SearchRequest("serverlog_20180710");//限定index
searchRequest.types("log");//限定type
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.aggregation(aggregationBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);
System.out.println(searchResponse);
Aggregations aggregations = searchResponse.getAggregations();
List<Aggregation> aggregationList = aggregations.asList();
for(Aggregation each: aggregationList){
System.out.println(each);
}
}finally{
HighLevelClient.close();
}
}
@Test
public void reverseToRootGroupByOnNestedFieldWithFilterTestWithReverseNestedNoPath() throws Exception {
Aggregations result = query(String.format("SELECT COUNT(*) FROM %s/nestedType GROUP BY nested(message.info),filter('myFilter',message.info = 'a'),reverse_nested(someField)", TEST_INDEX_NESTED_TYPE));
InternalNested nested = result.get("[email protected]");
InternalFilter filter = nested.getAggregations().get("[email protected]");
Terms infos = filter.getAggregations().get("message.info");
Assert.assertEquals(1,infos.getBuckets().size());
for(Terms.Bucket bucket : infos.getBuckets()) {
InternalReverseNested reverseNested = bucket.getAggregations().get("[email protected]");
Terms terms = reverseNested.getAggregations().get("someField");
Terms.Bucket internalBucket = terms.getBuckets().get(0);
long count = ((ValueCount) internalBucket.getAggregations().get("COUNT(*)")).getValue();
String key = internalBucket.getKey().toString();
if(key.equalsIgnoreCase("b")) {
Assert.assertEquals(2, count);
}
else {
throw new Exception(String.format("Unexpected key. expected: only a . found: %s", key));
}
}
}
private Aggregation resolveChildAggregation(Aggregations aggregations, String targetAggregationName) {
if (aggregations == null) return null;
for (Aggregation aggregation : aggregations) {
// Check if 'aggregation' is already the target aggregation.
if (aggregation.getName().equals(targetAggregationName)) {
return aggregation;
}
// Otherwise check all sub aggregations if applicable.
if (HasAggregations.class.isAssignableFrom(aggregation.getClass())) {
Aggregation target = resolveChildAggregation(HasAggregations.class.cast(aggregation).getAggregations(), targetAggregationName);
if (target != null) return target;
}
}
// Couldn't find target aggregation.
return null;
}
@Override
public final InternalAggregation doReduce(Aggregations aggregations, ReduceContext context) {
preCollection();
List<String> bucketsPath = AggregationPath.parse(bucketsPaths()[0]).getPathElementsAsStringList();
for (Aggregation aggregation : aggregations) {
if (aggregation.getName().equals(bucketsPath.get(0))) {
bucketsPath = bucketsPath.subList(1, bucketsPath.size());
InternalMultiBucketAggregation multiBucketsAgg = (InternalMultiBucketAggregation) aggregation;
List<? extends Bucket> buckets = multiBucketsAgg.getBuckets();
for (int i = 0; i < buckets.size(); i++) {
Bucket bucket = buckets.get(i);
Double bucketValue = BucketHelpers.resolveBucketValue(multiBucketsAgg, bucket, bucketsPath, gapPolicy);
if (bucketValue != null && !Double.isNaN(bucketValue)) {
collectBucketValue(bucket.getKeyAsString(), bucketValue);
}
}
}
}
return buildAggregation(Collections.EMPTY_LIST, metaData());
}
@Test
public void groupByTestWithFilter() throws Exception {
Aggregations result = query(String.format("SELECT COUNT(*) FROM %s/account GROUP BY filter(gender='m'),gender", TEST_INDEX_ACCOUNT));
InternalFilter filter = result.get("filter(gender = 'm')@FILTER");
Terms gender = filter.getAggregations().get("gender");
for(Terms.Bucket bucket : gender.getBuckets()) {
String key = bucket.getKey().toString();
long count = ((ValueCount) bucket.getAggregations().get("COUNT(*)")).getValue();
if(key.equalsIgnoreCase("m")) {
Assert.assertEquals(507, count);
}
else {
throw new Exception(String.format("Unexpected key. expected: only m. found: %s", key));
}
}
}
@Test
public void histogramOnNestedField() throws Exception {
Aggregations result = query(String.format("select count(*) from %s/nestedType group by histogram('field'='message.dayOfWeek','nested'='message','interval'='2' , 'alias' = 'someAlias' )", TEST_INDEX_NESTED_TYPE));
InternalNested nested = result.get("[email protected]");
Histogram histogram = nested.getAggregations().get("someAlias");
for(Histogram.Bucket bucket : histogram.getBuckets()){
long count = ((ValueCount) bucket.getAggregations().get("COUNT(*)")).getValue();
String key = ((Double)bucket.getKey()).intValue()+"";
if(key.equals("0") || key.equals("4")){
Assert.assertEquals(2,count);
}
else if (key.equals("2")){
Assert.assertEquals(1,count);
}
else{
Assert.assertTrue("only 0 2 4 keys are allowed got:" + key,false);
}
}
}
@Test
public void groupByOnNestedFieldWithFilterTest() throws Exception {
Aggregations result = query(String.format("SELECT COUNT(*) FROM %s/nestedType GROUP BY nested(message.info),filter('myFilter',message.info = 'a')", TEST_INDEX_NESTED_TYPE));
InternalNested nested = result.get("[email protected]");
InternalFilter filter = nested.getAggregations().get("[email protected]");
Terms infos = filter.getAggregations().get("message.info");
Assert.assertEquals(1,infos.getBuckets().size());
for(Terms.Bucket bucket : infos.getBuckets()) {
String key = bucket.getKey().toString();
long count = ((ValueCount) bucket.getAggregations().get("COUNT(*)")).getValue();
if(key.equalsIgnoreCase("a")) {
Assert.assertEquals(2, count);
}
else {
throw new Exception(String.format("Unexpected key. expected: only a . found: %s", key));
}
}
}
@Test
public void multipleGroupByTest() throws Exception {
Set expectedAges = new HashSet<Integer>(ContiguousSet.create(Range.closed(20, 40), DiscreteDomain.integers()));
Map<String, Set<Integer>> buckets = new HashMap<>();
Aggregations result = query(String.format("SELECT COUNT(*) FROM %s/account GROUP BY gender, terms('field'='age','size'=200,'alias'='age')", TEST_INDEX_ACCOUNT));
Terms gender = result.get("gender");
for(Terms.Bucket genderBucket : gender.getBuckets()) {
String genderKey = genderBucket.getKey().toString();
buckets.put(genderKey, new HashSet<Integer>());
Terms ageBuckets = (Terms) genderBucket.getAggregations().get("age");
for(Terms.Bucket ageBucket : ageBuckets.getBuckets()) {
buckets.get(genderKey).add(Integer.parseInt(ageBucket.getKey().toString()));
}
}
Assert.assertEquals(2, buckets.keySet().size());
Assert.assertEquals(expectedAges, buckets.get("m"));
Assert.assertEquals(expectedAges, buckets.get("f"));
}
/**
* Returns the aggregation that is associated with the specified name. This method also validates that the retrieved aggregation exists.
*
* @param searchResponse the response of the search request
* @param aggregationName the name of the aggregation
*
* @return the aggregation
*/
public Terms getAggregation(SearchResponse searchResponse, String aggregationName)
{
// Retrieve the aggregations from the search response.
Aggregations aggregations = getAggregationsFromSearchResponse(searchResponse);
// Retrieve the specified aggregation.
Terms aggregation = aggregations.get(aggregationName);
// Fail if retrieved aggregation is null.
if (aggregation == null)
{
// Log the error along with the search response contents.
LOGGER.error("Failed to retrieve \"{}\" aggregation from the search response. searchResponse={}", aggregationName,
jsonHelper.objectToJson(searchResponse));
// Throw an exception.
throw new IllegalStateException("Invalid search result.");
}
return aggregation;
}
@Test
public void multipleGroupBysWithSize() throws Exception {
Set expectedAges = new HashSet<Integer>(ContiguousSet.create(Range.closed(20, 40), DiscreteDomain.integers()));
Map<String, Set<Integer>> buckets = new HashMap<>();
Aggregations result = query(String.format("SELECT COUNT(*) FROM %s/account GROUP BY gender, terms('alias'='ageAgg','field'='age','size'=3)", TEST_INDEX_ACCOUNT));
Terms gender = result.get("gender");
Assert.assertEquals(2,gender.getBuckets().size());
for(Terms.Bucket genderBucket : gender.getBuckets()) {
String genderKey = genderBucket.getKey().toString();
buckets.put(genderKey, new HashSet<Integer>());
Terms ageBuckets = genderBucket.getAggregations().get("ageAgg");
Assert.assertEquals(3,ageBuckets.getBuckets().size());
}
}
/**
* Returns a representation of a set of aggregations from the nested aggregation. This method also validates that the retrieved object is not null.
*
* @param nestedAggregation the nested aggregation
* @param searchResponse the response of the search request
*
* @return the aggregations
*/
protected Aggregations getAggregationsFromNestedAggregation(Nested nestedAggregation, SearchResponse searchResponse)
{
// Retrieve the aggregations.
Aggregations aggregations = nestedAggregation.getAggregations();
// Fail if the retrieved object is null.
if (aggregations == null)
{
// Log the error along with the nested aggregation contents.
LOGGER.error("Failed to retrieve aggregations from the nested aggregation. searchResponse={} nestedAggregation={}",
jsonHelper.objectToJson(searchResponse), jsonHelper.objectToJson(nestedAggregation));
// Throw an exception.
throw new IllegalStateException("Invalid search result.");
}
return aggregations;
}
/**
* Returns a representation of a set of aggregations from the search response. This method also validates that the retrieved object is not null.
*
* @param searchResponse the response of the search request
*
* @return the aggregations
*/
protected Aggregations getAggregationsFromSearchResponse(SearchResponse searchResponse)
{
// Retrieve the aggregations.
Aggregations aggregations = searchResponse.getAggregations();
// Fail if the retrieved object is null.
if (aggregations == null)
{
// Log the error along with the search response contents.
LOGGER.error("Failed to retrieve aggregations from the search response. searchResponse={}", jsonHelper.objectToJson(searchResponse));
// Throw an exception.
throw new IllegalStateException("Invalid search result.");
}
return aggregations;
}
@Test
public void testGetNestedTagTagIndexSearchResponseDtoSearchResponseParameter()
{
SearchResponse searchResponse = mock(SearchResponse.class);
Aggregations aggregations = mock(Aggregations.class);
when(searchResponse.getAggregations()).thenReturn(aggregations);
Nested nestedAggregation = mock(Nested.class);
when(aggregations.get(TAG_FACET_AGGS)).thenReturn(nestedAggregation);
Aggregations aggregationAggregations = mock(Aggregations.class);
when(nestedAggregation.getAggregations()).thenReturn(aggregationAggregations);
Terms subAggregation = mock(Terms.class);
when(aggregationAggregations.get(TAGTYPE_CODE_AGGREGATION)).thenReturn(subAggregation);
List<TagTypeIndexSearchResponseDto> result = elasticsearchHelper.getNestedTagTagIndexSearchResponseDto(searchResponse);
assertThat("Result is null.", result, is(notNullValue()));
}
@Test
public void testGetResultTypeIndexSearchResponseDto()
{
SearchResponse searchResponse = mock(SearchResponse.class);
Terms terms = mock(Terms.class);
Aggregations aggregations = mock(Aggregations.class);
Terms.Bucket bucket = mock(Terms.Bucket.class);
List<Terms.Bucket> buckets = Collections.singletonList(bucket);
when(searchResponse.getAggregations()).thenReturn(aggregations);
when(aggregations.get(RESULT_TYPE_AGGS)).thenReturn(terms);
when(terms.getBuckets()).thenReturn(buckets);
when(bucket.getKeyAsString()).thenReturn(TAG_CODE);
when(bucket.getDocCount()).thenReturn(TAG_COUNT);
List<ResultTypeIndexSearchResponseDto> expectedList = new ArrayList<>();
expectedList.add(new ResultTypeIndexSearchResponseDto(TAG_CODE, TAG_COUNT, TAG_CODE));
List<ResultTypeIndexSearchResponseDto> resultList = elasticsearchHelper.getResultTypeIndexSearchResponseDto(searchResponse);
assertEquals(expectedList, resultList);
}
private StatsResponse buildResponse(StatsRequest request, Aggregations aggregations) {
// First build root level stats value
StatsValue statsValue = buildStatsValue(request.getField(), aggregations);
// Now build nested stats if present
List<BucketResponse<StatsValue>> buckets = null;
if (!CollectionUtils.isNullOrEmpty(request.getNesting())) {
buckets = buildNestedStats(request.getNesting(), aggregations);
}
StatsResponse statsResponse = new StatsResponse();
statsResponse.setResult(statsValue);
statsResponse.setBuckets(buckets);
return statsResponse;
}
@Test
public void reverseAnotherNestedGroupByOnNestedFieldWithFilterTestWithReverseNestedNoPath() throws Exception {
Aggregations result = query(String.format("SELECT COUNT(*) FROM %s/nestedType GROUP BY nested(message.info),filter('myFilter',message.info = 'a'),reverse_nested(comment.data,'~comment')", TEST_INDEX_NESTED_TYPE));
InternalNested nested = result.get("[email protected]");
InternalFilter filter = nested.getAggregations().get("[email protected]");
Terms infos = filter.getAggregations().get("message.info");
Assert.assertEquals(1,infos.getBuckets().size());
for(Terms.Bucket bucket : infos.getBuckets()) {
InternalReverseNested reverseNested = bucket.getAggregations().get("[email protected]_REVERSED");
InternalNested innerNested = reverseNested.getAggregations().get("[email protected]");
Terms terms = innerNested.getAggregations().get("comment.data");
Terms.Bucket internalBucket = terms.getBuckets().get(0);
long count = ((ValueCount) internalBucket.getAggregations().get("COUNT(*)")).getValue();
String key = internalBucket.getKey().toString();
if(key.equalsIgnoreCase("ab")) {
Assert.assertEquals(2, count);
}
else {
throw new Exception(String.format("Unexpected key. expected: only a . found: %s", key));
}
}
}
private List<GroupResult> getGroupResults(GroupRequest groupRequest, int index, Aggregations aggregations, Map<String, FieldType> commonColumnMetadata) {
List<Group> groups = groupRequest.getGroups();
String field = groups.get(index).getField();
List<GroupResult> searchResultGroups = new ArrayList<>();
if(aggregations != null) {
Terms terms = aggregations.get(getGroupByAggregationName(field));
for (Bucket bucket : terms.getBuckets()) {
GroupResult groupResult = new GroupResult();
groupResult.setKey(formatKey(bucket.getKey(), commonColumnMetadata.get(field)));
groupResult.setTotal(bucket.getDocCount());
Optional<String> scoreField = groupRequest.getScoreField();
if (scoreField.isPresent()) {
Sum score = bucket.getAggregations().get(getSumAggregationName(scoreField.get()));
groupResult.setScore(score.getValue());
}
if (index < groups.size() - 1) {
groupResult.setGroupedBy(groups.get(index + 1).getField());
groupResult.setGroupResults(getGroupResults(groupRequest, index + 1, bucket.getAggregations(), commonColumnMetadata));
}
searchResultGroups.add(groupResult);
}
}
return searchResultGroups;
}
private List<BucketResponse<List<StatsTrendValue>>> buildNestedTrendStats(
List<String> nesting,
Aggregations aggregations) {
final String field = nesting.get(0);
final List<String> remainingFields = (nesting.size() > 1)
? nesting.subList(1, nesting.size())
: new ArrayList<>();
Terms terms = aggregations.get(Utils.sanitizeFieldForAggregation(field));
List<BucketResponse<List<StatsTrendValue>>> bucketResponses = Lists.newArrayList();
for (Terms.Bucket bucket : terms.getBuckets()) {
BucketResponse<List<StatsTrendValue>> bucketResponse = new BucketResponse<>();
bucketResponse.setKey(String.valueOf(bucket.getKey()));
if (nesting.size() == 1) {
bucketResponse.setResult(buildStatsTrendValue(getParameter().getField(), bucket.getAggregations()));
}
else {
bucketResponse.setBuckets(buildNestedTrendStats(remainingFields, bucket.getAggregations()));
}
bucketResponses.add(bucketResponse);
}
return bucketResponses;
}
@Test
public void testSimpleSubAggregations() throws Exception {
final String query = String.format("SELECT /*! DOCS_WITH_AGGREGATION(10) */ * FROM %s/account GROUP BY (gender), (state) ", TEST_INDEX_ACCOUNT);
SqlElasticSearchRequestBuilder select = getSearchRequestBuilder(query);
SearchResponse response = (SearchResponse) select.get();
Aggregations result = response.getAggregations();
Terms gender = result.get("gender");
for(Terms.Bucket genderBucket : gender.getBuckets()) {
String genderKey = genderBucket.getKey().toString();
Assert.assertTrue("Gender should be m or f", genderKey.equals("m") || genderKey.equals("f"));
}
Assert.assertEquals(2, gender.getBuckets().size());
Terms state = result.get("state");
for(Terms.Bucket stateBucket : state.getBuckets()) {
if(stateBucket.getKey().toString().equalsIgnoreCase("ak")) {
Assert.assertTrue("There are 22 entries for state ak", stateBucket.getDocCount() == 22);
}
}
Assert.assertEquals(response.getHits().getTotalHits().value, 1000);
Assert.assertEquals(response.getHits().getHits().length, 10);
}
@Test
public void groupByTest() throws Exception {
Aggregations result = query(String.format("SELECT COUNT(*) FROM %s/account GROUP BY gender", TEST_INDEX_ACCOUNT));
Terms gender = result.get("gender");
for(Terms.Bucket bucket : gender.getBuckets()) {
String key = bucket.getKey().toString();
long count = ((ValueCount) bucket.getAggregations().get("COUNT(*)")).getValue();
if(key.equalsIgnoreCase("m")) {
Assert.assertEquals(507, count);
}
else if(key.equalsIgnoreCase("f")) {
Assert.assertEquals(493, count);
}
else {
throw new Exception(String.format("Unexpected key. expected: m OR f. found: %s", key));
}
}
}
@Test
public void reverseToRootGroupByOnNestedFieldWithFilterAndSumOnReverseNestedField() throws Exception {
Aggregations result = query(String.format("SELECT sum(reverse_nested(myNum)) bla FROM %s/nestedType GROUP BY nested(message.info),filter('myFilter',message.info = 'a')", TEST_INDEX_NESTED_TYPE));
InternalNested nested = result.get("[email protected]");
InternalFilter filter = nested.getAggregations().get("[email protected]");
Terms infos = filter.getAggregations().get("message.info");
Assert.assertEquals(1,infos.getBuckets().size());
for(Terms.Bucket bucket : infos.getBuckets()) {
InternalReverseNested reverseNested = bucket.getAggregations().get("[email protected]");
InternalSum sum = reverseNested.getAggregations().get("bla");
Assert.assertEquals(5.0,sum.getValue(),0.000001);
}
}
/**
* 赋值当天统计
*/
private void setCurrDate(Map<String, Object> result, Aggregations aggregations) {
ParsedDateRange currDate = aggregations.get("currDate");
Range.Bucket bucket = currDate.getBuckets().get(0);
Cardinality cardinality = bucket.getAggregations().get("uv");
result.put("currDate_pv", bucket.getDocCount());
result.put("currDate_uv", cardinality.getValue());
}
/**
* 赋值周统计
*/
private void setCurr24Hour(Map<String, Object> result, Aggregations aggregations) {
ParsedDateRange curr24Hour = aggregations.get("curr24Hour");
Range.Bucket bucket = curr24Hour.getBuckets().get(0);
//赋值天趋势统计
setStatDate(result, bucket.getAggregations());
}
private Missing getMissingAggregation(Aggregations aggs, Attribute attr) {
Aggregation agg = aggs.get(attr.getName() + FieldConstants.AGGREGATION_MISSING_POSTFIX);
if (agg == null) {
throw new RuntimeException("Missing missing aggregation");
}
if (!(agg instanceof Missing)) {
throw new RuntimeException("Aggregation is not a missing aggregation");
}
return (Missing) agg;
}
/**
* 赋值单字段统计
*/
private void setTermsData(Map<String, Object> result, Aggregations aggregations, String key) {
Terms terms = aggregations.get(key);
List<String> legendData = new ArrayList<>();
List<AggItemVo> datas = new ArrayList<>();
for (Terms.Bucket bucket : terms.getBuckets()) {
legendData.add((String)bucket.getKey());
AggItemVo item = new AggItemVo();
item.setName((String)bucket.getKey());
item.setValue(bucket.getDocCount());
datas.add(item);
}
result.put(key+"_legendData", legendData);
result.put(key+"_datas", datas);
}
@Test
public void geoBounds() throws SQLFeatureNotSupportedException, SqlParseException {
Aggregations result = query(String.format("SELECT * FROM %s/location GROUP BY geo_bounds(field='center',alias='bounds') ", TEST_INDEX_LOCATION));
InternalGeoBounds bounds = result.get("bounds");
Assert.assertEquals(0.5,bounds.bottomRight().getLat(),0.001);
Assert.assertEquals(105.0,bounds.bottomRight().getLon(),0.001);
Assert.assertEquals(5.0,bounds.topLeft().getLat(),0.001);
Assert.assertEquals(100.5,bounds.topLeft().getLon(),0.001);
}