lookup in mongodb aggregation

前端 未结 1 1428
不思量自难忘°
不思量自难忘° 2020-12-11 21:36

The following bson is personaddress collection:

{ 
        \"id\" : \"123456\", 
        \"name\" : \"foo\", 
        \"address\" : [
                


        
1条回答
  •  时光说笑
    2020-12-11 22:29

    Since you have nested arrays, you need to apply the $unwind operator first in order to denormalise the embedded documents before using the $lookup pipeline (unless you have already flattened them in your aggregation operation):

    db.personaddress.aggregate([
        { "$unwind": "$address" },
        { "$unwind": "$address.location" },
        {
            "$lookup": {
                "from": "places", 
                "localField": "address.location.place._id", 
                "foreignField": "_id", 
                "as": "address.location.place", 
            }
        }
    ])
    

    which can then be implemented as (untested):

    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 aggResults = mongoTemplate.aggregate(
        agg, PersonAddressDocument.class, OutputDocument.class
    );
    

    If your Spring Data version does not support this, a workaround is to implement the AggregationOperation interface to take in a DBObject:

    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);
        }
    }
    

    Then implement the $lookup operation as a DBObject in the aggregation pipeline:

    DBObject lookupOperation = (DBObject)new BasicDBObject(
        "$lookup", new BasicDBObject("from", "places")
            .append("localField", "address.location.place._id")
            .append("foreignField", "_id")
            .append("as", "address.location.place")       
    );
    

    which you can then use as:

    Aggregation agg = newAggregation(
        unwind("address"),
        unwind("address.location"),
        lookupOperation  
    );
    
    AggregationResults aggResults = mongoTemplate.aggregate(
        agg, PersonAddressDocument.class, OutputDocument.class
    );
    

    0 讨论(0)
提交回复
热议问题