// http://docs.mongodb.org/manual/reference/operator/near/#op._S_near
 @Override
 public Filter createFilter(final List<String> path, DBObject refExpression) {
   LOG.debug("path:{}, refExp:{}", path, refExpression);
   Number maxDistance = typecast(MAX_DISTANCE, refExpression.get(MAX_DISTANCE), Number.class);
   final List<LatLong> coordinates;
   if (refExpression.get(command) instanceof BasicDBList) {
     coordinates =
         GeoUtil.latLon(
             Collections.singletonList(command),
             refExpression); // typecast(command, refExpression.get(command), List.class);
   } else {
     DBObject dbObject = typecast(command, refExpression.get(command), DBObject.class);
     coordinates = GeoUtil.latLon(Arrays.asList("$geometry", "coordinates"), dbObject);
   }
   return createNearFilter(path, coordinates, maxDistance, spherical);
 }
 // http://docs.mongodb.org/manual/reference/operator/query/geoWithin/
 @Override
 public Filter createFilter(final List<String> path, DBObject refExpression) {
   LOG.info("geoWithin path:{}, refExp:{}", path, refExpression);
   Geometry geometry =
       GeoUtil.getGeometry(
           typecast("$geoWithin", refExpression.get("$geoWithin"), DBObject.class));
   return createGeowithinFilter(path, geometry);
 }
  // @VisibleForTesting
  protected int compareTo(Object c1, Object c2) { // Object to handle MinKey/MaxKey
    Object cc1 = c1;
    Object cc2 = c2;
    Class<?> clazz1 = c1 == null ? Null.class : c1.getClass();
    Class<?> clazz2 = c2 == null ? Null.class : c2.getClass();
    // Not comparable for MinKey/MaxKey
    if (!clazz1.equals(clazz2) || !(cc1 instanceof Comparable)) {
      boolean checkTypes = true;
      if (cc1 instanceof Number) {
        if (cc2 instanceof Number) {
          cc1 = new BigDecimal(cc1.toString());
          cc2 = new BigDecimal(cc2.toString());
          checkTypes = false;
        }
      }
      if (cc1 instanceof Binary) {
        cc1 = convertFrom((Binary) cc1);
        checkTypes = false;
      }
      if (cc2 instanceof Binary) {
        cc2 = convertFrom((Binary) cc2);
        checkTypes = false;
      }
      if (cc1 instanceof byte[]) {
        cc1 = convertFrom((byte[]) cc1);
        checkTypes = false;
      }
      if (cc2 instanceof byte[]) {
        cc2 = convertFrom((byte[]) cc2);
        checkTypes = false;
      }
      //      if (cc1 instanceof ObjectId && cc2 instanceof String && ObjectId.isValid((String)
      // cc2)) {
      //        cc2 = ObjectId.massageToObjectId(cc2);
      //        checkTypes = false;
      //      }
      //      if (cc2 instanceof ObjectId && cc1 instanceof String && ObjectId.isValid((String)
      // cc1)) {
      //        cc1 = ObjectId.massageToObjectId(cc2);
      //        checkTypes = false;
      //      }
      LatLong ll1 = GeoUtil.getLatLong(cc1);
      if (ll1 != null) {
        LatLong ll2 = GeoUtil.getLatLong(cc2);
        if (ll2 != null) {
          cc1 = ll1;
          cc2 = ll2;
          checkTypes = false;
        }
      }
      if (cc1 instanceof DBRefBase && cc2 instanceof DBRefBase) {
        DBRefBase a1 = (DBRefBase) cc1;
        DBRefBase a2 = (DBRefBase) cc2;
        if (a1.equals(a2)) {
          return 0;
        }
        // Not the idea of the year..
        cc1 = a1.toString();
        cc2 = a2.toString();
        checkTypes = false;
      }
      if (checkTypes) {
        Integer type1 = CLASS_TO_WEIGHT.get(clazz1);
        Integer type2 = CLASS_TO_WEIGHT.get(clazz2);
        if (type1 != null && type2 != null) {
          cc1 = type1;
          cc2 = type2;
        } else {
          throw new FongoException(
              "Don't know how to compare "
                  + cc1.getClass()
                  + " and "
                  + cc2.getClass()
                  + " values are : "
                  + c1
                  + " vs "
                  + c2);
        }
      }
    }

    //    LOG.info("\tcompareTo() cc1:[{}], cc2:[{}] => {}", cc1, cc2, ((Comparable)
    // cc1).compareTo(cc2));
    return ((Comparable) cc1).compareTo(cc2);
  }