java.lang.IllegalArgumentException: 在MongoDB中执行聚合时无效的引用

4

我有一个集合中的文档:

{
    "_id": ObjectId("5ab273ed31fa764560a912f8"),
    "hourNumber": 21,
    "errorSegments": [{
        "agentName": "agentX"
    },
    {
        "agentName": "agentY"
    }]
}

我会尝试在Spring Boot中执行以下聚合函数,以便检索与代理匹配的特定小时的"errorSegments"。在Mongo shell中运行良好:
工作的shell:
db.errorsegment.aggregate([{
    "$match": {
        "hourNumber": 21,
        "errorSegments.agentName": "agentX"
    }
},
{
    "$project": {
        "errorSegments": {
            "$filter": {
                "input": "$errorSegments",
                "as": "e",
                "cond": {
                    "$eq": ["$$e.agentName",
                    "agentX"]
                }
            }
        }
    }
},
{
    "$unwind": "$errorSegments"
},
{
    "$replaceRoot": {
        "newRoot": "$errorSegments"
    }
}])

所以它仅提供输出,这是所需的结果:
{ "agentName" : "agentX" }

但是我在Spring中的以下代码出现了错误:
MatchOperation match = Aggregation.match(Criteria.where("hourNumber").is(21).and("errorSegments.agentName").is("agentX"));

        ProjectionOperation project = Aggregation.project()
                  .and(new AggregationExpression() {

                      @Override
                        public DBObject toDbObject(AggregationOperationContext context) {

                          DBObject filterExpression = new BasicDBObject();
                          filterExpression.put("input", "$errorSegments");
                          filterExpression.put("as", "e");
                          filterExpression.put("cond", new BasicDBObject("$eq", Arrays.<Object> asList("$$e.agentName","agentX")));

                          return new BasicDBObject("$filter", filterExpression);
                      } }).as("prop");


        UnwindOperation unwind = Aggregation.unwind("$errorSegments");

        ReplaceRootOperation replaceRoot = Aggregation.replaceRoot("$errorSegments");

        Aggregation aggregation = Aggregation.newAggregation(match,project,unwind,replaceRoot);

        AggregationResults<ErrorSegment> errorSegments = mongoOps.aggregate(aggregation, SegmentAudit.class , ErrorSegment.class);

以下是日志记录内容:
java.lang.IllegalArgumentException: Invalid reference 'errorSegments'!
    at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:99) ~[spring-data-mongodb-1.10.3.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:71) ~[spring-data-mongodb-1.10.3.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.aggregation.UnwindOperation.toDBObject(UnwindOperation.java:95) ~[spring-data-mongodb-1.10.3.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.aggregation.AggregationOperationRenderer.toDBObject(AggregationOperationRenderer.java:56) ~[spring-data-mongodb-1.10.3.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.aggregation.Aggregation.toDbObject(Aggregation.java:580) ~[spring-data-mongodb-1.10.3.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1567) ~[spring-data-mongodb-1.10.3.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1502) ~[spring-data-mongodb-1.10.3.RELEASE.jar:na]
1个回答

5
错误的源头是您在过滤操作中使用的别名。它应该是errorSegments而不是prop,但您还有其他问题。使用字段名即$前缀不正确。
以下是更新的聚合查询。您可以使用$filter助手。
MatchOperation match = Aggregation.match(Criteria.where("hourNumber").is(21).and("errorSegments.agentName").is("agentX"));
ProjectionOperation project = Aggregation.
            project().and(ArrayOperators.Filter.filter("errorSegments")
                    .as("e")
                    .by(ComparisonOperators.Eq.valueOf(
                            "e.agentName")
                            .equalToValue(
                                    "agentX")))
                    .as("errorSegments");
UnwindOperation unwind = Aggregation.unwind("errorSegments");
ReplaceRootOperation replaceRoot = Aggregation.replaceRoot("errorSegments");
Aggregation aggregation = Aggregation.newAggregation(match,project,unwind,replaceRoot);

以下是生成的查询语句。
[
  {
    "$match": {
      "hourNumber": 21,
      "errorSegments.agentName": "agentX"
    }
  },
  {
    "$project": {
      "errorSegments": {
        "$filter": {
          "input": "$errorSegments",
          "as": "e",
          "cond": {
            "$eq": [
              "$$e.agentName",
              "agentX"
            ]
          }
        }
      }
    }
  },
  {
    "$unwind": "$errorSegments"
  },
  {
    "$replaceRoot": {
      "newRoot": "$errorSegments"
    }
  }
]

1
非常感谢,运行得很好。您能否推荐一些高级操作的良好来源,例如这些?因为我在Spring Mongo文档中找不到它们。 - devcodes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接