Mon go агрегация для поля DbRef с mongoTemplate - PullRequest
1 голос
/ 17 марта 2020

Предположим, у меня есть две коллекции mon go следующим образом.

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

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

Что мне нужно, так это извлечь записи из коллекции A, у которых значение поля "level" имеет значение "super" и связано с ним Значение "role" записи коллекции B как "admin".

Для этого я пытаюсь использовать агрегацию и java mongoTemplate.

Ниже приведен код, который я пробовал, но он возвращает 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);

Обратите внимание, что я новичок в пн go агрегации.

1 Ответ

1 голос
/ 17 марта 2020

Это тихое уродливое решение:

MongoTemplate

Вы не можете использовать TypedAggregation, потому что нам нужно преобразовать A коллекцию, чтобы иметь возможность объединиться с B collection

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

...