protected SortOptions.Builder buildSortOptions(List<OrderComponent> order) {
   SortOptions.Builder sortOptions = SortOptions.newBuilder();
   for (OrderComponent sort : order) {
     String fieldName = getEncodedFieldName(sort.getField());
     SortExpression.Builder expression = SortExpression.newBuilder().setExpression(fieldName);
     expression =
         expression.setDirection(
             sort.isAscending()
                 ? SortExpression.SortDirection.ASCENDING
                 : SortExpression.SortDirection.DESCENDING);
     IndexType indexType = metadata.getIndexType(sort.getField());
     if (IndexType.SmallDecimal == indexType || IndexType.BigDecimal == indexType) {
       expression = expression.setDefaultValueNumeric(sort.isDescending() ? IntLow : IntHigh);
     } else if (IndexType.Date == indexType) {
       expression = expression.setDefaultValueDate(sort.isDescending() ? DateLow : DateHigh);
     } else {
       expression = expression.setDefaultValue(sort.isDescending() ? StringLow : StringHigh);
     }
     sortOptions = sortOptions.addSortExpression(expression);
   }
   return sortOptions;
 }
  // Search for nearby places
  @Override
  public CursorPage<DProduct, String> searchForNearby(
      int pageSize,
      String cursor,
      Float latitude,
      Float longitude,
      int radius,
      RnrService.SortOrder sortOrder) {

    // Build the query string
    String queryString =
        String.format("distance(location, geopoint(%f, %f)) < %d", latitude, longitude, radius);

    // Sort expression
    SortExpression sortExpression = null;
    switch (sortOrder) {
      case DISTANCE:
        String sortString =
            String.format("distance(location, geopoint(%f, %f))", latitude, longitude);
        sortExpression =
            SortExpression.newBuilder()
                .setExpression(sortString)
                .setDirection(SortExpression.SortDirection.ASCENDING)
                .setDefaultValueNumeric(radius + 1)
                .build();
        break;
      case TOP_RATED:
        sortExpression =
            SortExpression.newBuilder()
                .setExpression("averageRating")
                .setDirection(SortExpression.SortDirection.DESCENDING)
                .setDefaultValue("")
                .build();
        break;
      case MOST_LIKED:
        sortExpression =
            SortExpression.newBuilder()
                .setExpression("likeCount")
                .setDirection(SortExpression.SortDirection.DESCENDING)
                .setDefaultValue("")
                .build();
        break;
      case MOST_THUMBS_UP:
        sortExpression =
            SortExpression.newBuilder()
                .setExpression("thumbsUp")
                .setDirection(SortExpression.SortDirection.DESCENDING)
                .setDefaultValue("")
                .build();
        break;
    }

    // Options
    QueryOptions options = null;
    QueryOptions.Builder builder =
        QueryOptions.newBuilder()
            .setSortOptions(SortOptions.newBuilder().addSortExpression(sortExpression))
            .setLimit(pageSize);

    if (null != cursor)
      builder.setCursor(com.google.appengine.api.search.Cursor.newBuilder().build(cursor));

    // Build query
    com.google.appengine.api.search.Query query =
        com.google.appengine.api.search.Query.newBuilder().setOptions(options).build(queryString);

    return searchInIndexWithQuery(query, getLocationIndex());
  }