Da Sie verschachtelte Arrays haben, müssen Sie $unwind
anwenden Operator zuerst, um die eingebetteten Dokumente zu denormalisieren, bevor $lookup
verwendet wird Pipeline (es sei denn, Sie haben sie bereits in Ihrem Aggregationsvorgang vereinfacht):
db.personaddress.aggregate([
{ "$unwind": "$address" },
{ "$unwind": "$address.location" },
{
"$lookup": {
"from": "places",
"localField": "address.location.place._id",
"foreignField": "_id",
"as": "address.location.place",
}
}
])
was dann implementiert werden kann als (ungetestet):
LookupOperation lookupOperation = LookupOperation.newLookup()
.from("places")
.localField("address.location.place._id")
.foreignField("_id")
.as("address.location.place");
Aggregation agg = newAggregation(
unwind("address"),
unwind("address.location"),
lookupOperation
);
AggregationResults<OutputDocument> aggResults = mongoTemplate.aggregate(
agg, PersonAddressDocument.class, OutputDocument.class
);
Wenn Ihre Spring Data-Version dies nicht unterstützt, besteht eine Problemumgehung darin, die AggregationOperation zu implementieren Schnittstelle, um ein DBObject
aufzunehmen :
public class CustomGroupOperation implements AggregationOperation {
private DBObject operation;
public CustomGroupOperation (DBObject operation) {
this.operation = operation;
}
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return context.getMappedObject(operation);
}
}
Implementieren Sie dann $lookup
Betrieb als DBObject in der Aggregationspipeline:
DBObject lookupOperation = (DBObject)new BasicDBObject(
"$lookup", new BasicDBObject("from", "places")
.append("localField", "address.location.place._id")
.append("foreignField", "_id")
.append("as", "address.location.place")
);
die Sie dann verwenden können als:
Aggregation agg = newAggregation(
unwind("address"),
unwind("address.location"),
lookupOperation
);
AggregationResults<OutputDocument> aggResults = mongoTemplate.aggregate(
agg, PersonAddressDocument.class, OutputDocument.class
);