Mongo 使用 mongoTemplate 聚合 DbRef 字段

Mongo aggregation for a DbRef field with mongoTemplate

假设我有两个 mongo 集合如下。

Collection A
{ 
    "_id" : ObjectId("582abcd85d2dfa67f44127e0"),
    "level" : "super"
    "dataReference" : Object
        B : DbRef(B, 5b618a570550de0021aaa2ef, undefined)
}

Collection B
{ 
    "_id" : ObjectId("5b618a570550de0021aaa2ef"),  
    "role" : "admin"
}

我需要从集合 A 中检索记录,这些记录的 "level" 字段值为 "super",其相关集合 B 记录的 "role" 值为 "admin" .

为此,我正在尝试使用聚合和 java mongo模板。

以下是我试过的代码,但它 returns 0 条记录。

final TypedAggregation<A> typedAggregation = Aggregation.newAggregation(A.class,
                Aggregation.match(Criteria.where("level").equals(level)),
                Aggregation.lookup("B", "_id", "dataReference.B.$id", "Basb"),
                Aggregation.match(new Criteria().andOperator(
                        Criteria.where("B.role").regex("admin")
                )));

        final AggregationResults<Map> A = mongoTemplate.aggregate(typedAggregation, "A", Map.class);

请注意,我是 Mongo 聚合的新手。

这是安静丑陋的解决方案:

MongoTemplate

您不能使用 TypedAggregation,因为我们需要转换 A 集合才能加入 B 集合

Aggregation typedAggregation = Aggregation.newAggregation(
    Aggregation.match(Criteria.where("level").is("super")),
    new AggregationOperation() {
        @Override
        public Document toDocument(AggregationOperationContext context) {
            return Document.parse("{\"$addFields\":{\"dataReference\":{\"$reduce\":{\"input\":{\"$objectToArray\":\"$dataReference\"},\"initialValue\":null,\"in\":{\"$cond\":[{\"$eq\":[{\"$type\":\"$$this.v\"},\"objectId\"]},\"$$this.v\",\"$$value\"]}}}}}");
        }
    },
    Aggregation.lookup("B", "dataReference", "_id", "B"),
    Aggregation.match(new Criteria().andOperator(
             Criteria.where("B.role").regex("admin")
        )
    )
);

final AggregationResults<Document> A = mongoTemplate.aggregate(typedAggregation, "A", Document.class);

MongoDB聚合

db.A.aggregate([
  {
    "$match": {
      "level": "super"
    }
  },
  {
    "$addFields": {
      "B": {
        "$reduce": {
          "input": {
            "$objectToArray": "$dataReference"
          },
          "initialValue": null,
          "in": {
            "$cond": [
              {
                "$eq": [
                  {
                    "$type": "$$this.v"
                  },
                  "objectId"
                ]
              },
              "$$this.v",
              "$$value"
            ]
          }
        }
      }
    }
  },
  {
    "$lookup": {
      "from": "B",
      "localField": "B",
      "foreignField": "_id",
      "as": "B"
    }
  },
  {
    "$match": {
      "$and": [
        {
          "B.role": {
            "$regex": "admin",
            "$options": ""
          }
        }
      ]
    }
  }
])

MongoPlayground