in grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/query/MongoQuery.java [112:351]
static {
queryHandlers.put(IdEquals.class, new QueryHandler<IdEquals>() {
public void handle(EmbeddedQueryEncoder queryEncoder, IdEquals criterion, Document query, PersistentEntity entity) {
Object value = criterion.getValue();
MappingContext mappingContext = entity.getMappingContext();
PersistentProperty identity = entity.getIdentity();
Object converted = mappingContext.getConversionService().convert(value, identity.getType());
query.put(MongoEntityPersister.MONGO_ID_FIELD, converted);
}
});
queryHandlers.put(AssociationQuery.class, new QueryHandler<AssociationQuery>() {
public void handle(EmbeddedQueryEncoder queryEncoder, AssociationQuery criterion, Document query, PersistentEntity entity) {
Association<?> association = criterion.getAssociation();
PersistentEntity associatedEntity = association.getAssociatedEntity();
if (association instanceof EmbeddedCollection) {
Document associationCollectionQuery = new Document();
populateMongoQuery(queryEncoder, associationCollectionQuery, criterion.getCriteria(), associatedEntity);
Document collectionQuery = new Document("$elemMatch", associationCollectionQuery);
String propertyKey = getPropertyName(entity, association.getName());
query.put(propertyKey, collectionQuery);
} else if (associatedEntity instanceof EmbeddedPersistentEntity || association instanceof Embedded) {
Document associatedEntityQuery = new Document();
populateMongoQuery(queryEncoder, associatedEntityQuery, criterion.getCriteria(), associatedEntity);
for (String property : associatedEntityQuery.keySet()) {
String propertyKey = getPropertyName(entity, association.getName());
query.put(propertyKey + '.' + property, associatedEntityQuery.get(property));
}
} else {
throw new UnsupportedOperationException("Join queries are not supported by MongoDB");
}
}
});
queryHandlers.put(WithinBox.class, new QueryHandler<WithinBox>() {
public void handle(EmbeddedQueryEncoder queryEncoder, WithinBox withinBox, Document query, PersistentEntity entity) {
Document nearQuery = new Document();
Document box = new Document();
MongoEntityPersister.setDBObjectValue(box, BOX_OPERATOR, withinBox.getValues(), entity.getMappingContext());
nearQuery.put(WITHIN_OPERATOR, box);
String propertyName = getPropertyName(entity, withinBox);
query.put(propertyName, nearQuery);
}
});
queryHandlers.put(WithinPolygon.class, new QueryHandler<WithinPolygon>() {
public void handle(EmbeddedQueryEncoder queryEncoder, WithinPolygon withinPolygon, Document query, PersistentEntity entity) {
Document nearQuery = new Document();
Document box = new Document();
MongoEntityPersister.setDBObjectValue(box, POLYGON_OPERATOR, withinPolygon.getValues(), entity.getMappingContext());
nearQuery.put(WITHIN_OPERATOR, box);
String propertyName = getPropertyName(entity, withinPolygon);
query.put(propertyName, nearQuery);
}
});
queryHandlers.put(WithinCircle.class, new QueryHandler<WithinCircle>() {
public void handle(EmbeddedQueryEncoder queryEncoder, WithinCircle withinCentre, Document query, PersistentEntity entity) {
Document nearQuery = new Document();
Document center = new Document();
MongoEntityPersister.setDBObjectValue(center, CENTER_OPERATOR, withinCentre.getValues(), entity.getMappingContext());
nearQuery.put(WITHIN_OPERATOR, center);
String propertyName = getPropertyName(entity, withinCentre);
query.put(propertyName, nearQuery);
}
});
QueryHandler<Near> nearHandler = new QueryHandler<Near>() {
public void handle(EmbeddedQueryEncoder queryEncoder, Near near, Document query, PersistentEntity entity) {
Document nearQuery = new Document();
Object value = near.getValue();
String nearOperator = near instanceof NearSphere ? NEAR_SPHERE_OPERATOR : NEAR_OPERATOR;
if ((value instanceof List) || (value instanceof Map)) {
MongoEntityPersister.setDBObjectValue(nearQuery, nearOperator, value, entity.getMappingContext());
} else if (value instanceof Point) {
Document geoJson = GeoJSONType.convertToGeoDocument((Point) value);
Document geometry = new Document();
geometry.put(GEOMETRY_OPERATOR, geoJson);
if (near.maxDistance != null) {
geometry.put(MAX_DISTANCE_OPERATOR, near.maxDistance.getValue());
}
nearQuery.put(nearOperator, geometry);
}
String propertyName = getPropertyName(entity, near);
query.put(propertyName, nearQuery);
}
};
queryHandlers.put(Near.class, nearHandler);
queryHandlers.put(NearSphere.class, nearHandler);
queryHandlers.put(GeoWithin.class, new QueryHandler<GeoWithin>() {
public void handle(EmbeddedQueryEncoder queryEncoder, GeoWithin geoWithin, Document query, PersistentEntity entity) {
Document queryRoot = new Document();
Document queryGeoWithin = new Document();
queryRoot.put(GEO_WITHIN_OPERATOR, queryGeoWithin);
String targetProperty = getPropertyName(entity, geoWithin);
Object value = geoWithin.getValue();
if (value instanceof Shape) {
Shape shape = (Shape) value;
if (shape instanceof Polygon) {
Polygon p = (Polygon) shape;
Document geoJson = GeoJSONType.convertToGeoDocument(p);
queryGeoWithin.put(GEOMETRY_OPERATOR, geoJson);
} else if (shape instanceof Box) {
queryGeoWithin.put(BOX_OPERATOR, shape.asList());
} else if (shape instanceof Circle) {
queryGeoWithin.put(CENTER_OPERATOR, shape.asList());
} else if (shape instanceof Sphere) {
queryGeoWithin.put(CENTER_SPHERE_OPERATOR, shape.asList());
}
} else if (value instanceof Map) {
queryGeoWithin.putAll((Map) value);
}
query.put(targetProperty, queryRoot);
}
});
queryHandlers.put(GeoIntersects.class, new QueryHandler<GeoIntersects>() {
public void handle(EmbeddedQueryEncoder queryEncoder, GeoIntersects geoIntersects, Document query, PersistentEntity entity) {
Document queryRoot = new Document();
Document queryGeoWithin = new Document();
queryRoot.put(GEO_INTERSECTS_OPERATOR, queryGeoWithin);
String targetProperty = getPropertyName(entity, geoIntersects);
Object value = geoIntersects.getValue();
if (value instanceof GeoJSON) {
Shape shape = (Shape) value;
Document geoJson = GeoJSONType.convertToGeoDocument(shape);
queryGeoWithin.put(GEOMETRY_OPERATOR, geoJson);
} else if (value instanceof Map) {
queryGeoWithin.putAll((Map) value);
}
query.put(targetProperty, queryRoot);
}
});
queryHandlers.put(Conjunction.class, new QueryHandler<Conjunction>() {
public void handle(EmbeddedQueryEncoder queryEncoder, Conjunction criterion, Document query, PersistentEntity entity) {
populateMongoQuery(queryEncoder, query, criterion, entity);
}
});
queryHandlers.put(Disjunction.class, new QueryHandler<Disjunction>() {
@SuppressWarnings("unchecked")
public void handle(EmbeddedQueryEncoder queryEncoder, Disjunction criterion, Document query, PersistentEntity entity) {
populateMongoQuery(queryEncoder, query, criterion, entity);
}
});
groupByProjectionHandlers.put(AvgProjection.class, new ProjectionHandler<AvgProjection>() {
@Override
public String handle(PersistentEntity entity, Document projectObject, Document groupBy, AvgProjection projection) {
return addProjectionToGroupBy(projectObject, groupBy, projection, AVERAGE_OPERATOR, "avg_");
}
});
groupByProjectionHandlers.put(CountProjection.class, new ProjectionHandler<CountProjection>() {
@Override
public String handle(PersistentEntity entity, Document projectObject, Document groupBy, CountProjection projection) {
projectObject.put(MongoEntityPersister.MONGO_ID_FIELD, 1);
String projectionKey = "count";
groupBy.put(projectionKey, new Document(SUM_OPERATOR, 1));
return projectionKey;
}
});
groupByProjectionHandlers.put(CountDistinctProjection.class, new ProjectionHandler<CountDistinctProjection>() {
@Override
// equivalent of "select count (distinct fieldName) from someTable". Example:
// db.someCollection.aggregate([{ $group: { _id: "$fieldName"} },{ $group: { _id: 1, count: { $sum: 1 } } } ])
public String handle(PersistentEntity entity, Document projectObject, Document groupBy, CountDistinctProjection projection) {
projectObject.put(projection.getPropertyName(), 1);
String property = projection.getPropertyName();
String projectionValueKey = "countDistinct_" + property;
Document id = getIdObjectForGroupBy(groupBy);
id.put(projectionValueKey, "$" + property);
return projectionValueKey;
}
});
groupByProjectionHandlers.put(MinProjection.class, new ProjectionHandler<MinProjection>() {
@Override
public String handle(PersistentEntity entity, Document projectObject, Document groupBy, MinProjection projection) {
return addProjectionToGroupBy(projectObject, groupBy, projection, MIN_OPERATOR, "min_");
}
});
groupByProjectionHandlers.put(MaxProjection.class, new ProjectionHandler<MaxProjection>() {
@Override
public String handle(PersistentEntity entity, Document projectObject, Document groupBy, MaxProjection projection) {
return addProjectionToGroupBy(projectObject, groupBy, projection, MAX_OPERATOR, "max_");
}
});
groupByProjectionHandlers.put(SumProjection.class, new ProjectionHandler<SumProjection>() {
@Override
public String handle(PersistentEntity entity, Document projectObject, Document groupBy, SumProjection projection) {
return addProjectionToGroupBy(projectObject, groupBy, projection, SUM_OPERATOR, "sum_");
}
});
projectProjectionHandlers.put(DistinctPropertyProjection.class, new ProjectionHandler<DistinctPropertyProjection>() {
@Override
public String handle(PersistentEntity entity, Document projectObject, Document groupBy, DistinctPropertyProjection projection) {
String property = projection.getPropertyName();
projectObject.put(property, 1);
Document id = getIdObjectForGroupBy(groupBy);
String projectedValueKey = property.replace('.', '_');
id.put(projectedValueKey, "$" + property);
return projectedValueKey;
}
});
projectProjectionHandlers.put(PropertyProjection.class, new ProjectionHandler<PropertyProjection>() {
@Override
public String handle(PersistentEntity entity, Document projectObject, Document groupBy, PropertyProjection projection) {
String property = projection.getPropertyName();
projectObject.put(property, 1);
Document id = getIdObjectForGroupBy(groupBy);
String projectedValueKey = property.replace('.', '_');
id.put(projectedValueKey, "$" + property);
// we add the id to the grouping to make it not distinct
id.put(MongoEntityPersister.MONGO_ID_FIELD, "$" + MongoEntityPersister.MONGO_ID_FIELD);
return projectedValueKey;
}
});
projectProjectionHandlers.put(IdProjection.class, new ProjectionHandler<IdProjection>() {
@Override
public String handle(PersistentEntity entity, Document projectObject, Document groupBy, IdProjection projection) {
projectObject.put(MongoEntityPersister.MONGO_ID_FIELD, 1);
Document id = getIdObjectForGroupBy(groupBy);
id.put(MongoEntityPersister.MONGO_ID_FIELD, "$_id");
return MongoEntityPersister.MONGO_ID_FIELD;
}
});
}