【问题标题】:Spring Data MongoDB non-existent switch errorSpring Data MongoDB不存在开关错误
【发布时间】:2021-01-04 00:40:57
【问题描述】:

我在春季使用 MongoDB 在我的一项服务后面运行聚合逻辑。

聚合逻辑如下所示:

MatchOperation dateMatchOperation = Aggregation.match(
    Criteria.
            where("date").
            gte(new Date(startStamp)).lte(new Date(endStamp)));

MatchOperation propertyMatchOperation = Aggregation.match(
    Criteria.
            where("abc1").is(abcVal1)
            .and("abc2").is(abcVal2)
            .and("abc3").is(abcVal3)
            .and("abc4").is(abcVal4)
            .and("abc5").is(abcVal5)
);

List<Date> dates = new ArrayList<>();
//Create appropriate interval arraylist which will be passed to mongo
for (int i = 0; i < (endStamp - startStamp)/aggregationInterval; i ++) {
dates.add(new Date(startStamp + i * aggregationInterval));
}


BucketOperation bucketOperation = Aggregation.bucket("date").withBoundaries(dates.toArray())
    .andOutput(AccumulatorOperators.Sum.sumOf(aggregationInput)).as("value")
    .andOutput(AccumulatorOperators.Min.minOf("date")).as("from")
    .andOutput(AccumulatorOperators.Max.maxOf("date")).as("to");


AggregationOptions aggregationOptions = AggregationOptions.builder().allowDiskUse(true).build();
AggregationResults<MetricAggregationResult> aggregationResults = mongoTemplate.aggregate(
    Aggregation.newAggregation(dateMatchOperation, propertyMatchOperation, bucketOperation)
        .withOptions(aggregationOptions),
    "mongocollectionname",
    MetricAggregationResult.class);

我正在用 450 万个文档对这个集合进行测试。当aggregationInterval 很小并且arraylist 中有很多元素时它可以正常工作,但是在某些时候,逐渐增加聚合间隔我注意到在某个点聚合之后会引发以下错误:

com.mongodb.MongoCommandException: Command failed with error 40066: '$switch could not find a matching branch for an input, and no default was specified.'

这很奇怪,因为我的逻辑中没有使用任何 $switch 聚合,至于 AggregationOptions,我认为 mongo aggregation was hitting it's 100MB limit 并且我允许使用磁盘。

此时我的双手被束缚了,我不知道是什么导致了问题(我在 StackOverflow 上搜索了 $switch 错误,但我找不到任何东西,因为所有提问的人都在他们的代码中使用了 $switch在某种程度上),但我非常有信心这是 mongo 方面错过的东西。

【问题讨论】:

    标签: mongodb spring-data aggregation-framework spring-data-mongodb


    【解决方案1】:
    To use a bucket operation, we specify the following:
    
    groupBy: the field that the boundaries will apply to. This field must be numeric or a date field.
    boundaries: an array of boundary points. Documents which have a groupBy field falling between two elements in the array go into that bucket. The between test here is half-open, so the first point is inclusive, second point is exclusive, which is the behavior developers would expect
    default: any documents in the pipeline which don’t go into one of the buckets will go into default. This is required. Using a match operation in the pipeline before the bucket operation will remove documents which shouldn’t be processed.
    output: an aggregation expression to generate the output document for each bucket
    
    
    IN the above code, we missed specifying default. 
    
    final BucketOperation bucketOperation = Aggregation.bucket("date").
                    withBoundaries(now.minus(10, ChronoUnit.DAYS), now.minus(9, DAYS),
                            now.minus(8, DAYS), now.minus(7, DAYS), now.minus(6, DAYS),
                            now.minus(5, DAYS), now.minus(4, DAYS), now.minus(3, DAYS),
                            now.minus(2, DAYS), now.minus(1, DAYS), now.minus(0, DAYS)).
                    withDefaultBucket("defaultBucket").
                    andOutput(countingExpression).as("count");
    

    请参考以下链接:- https://chiralsoftware.com/idea/spring-data-aggregation-operations

    【讨论】:

      【解决方案2】:
      Use BucketAutoOperation
      
       BucketAutoOperation bucketAutoOperation = Aggregation.bucketAuto("date", 2)
                      .andOutput(AccumulatorOperators.Sum.sumOf(aggregationInput)).as("value")
                      .andOutput(AccumulatorOperators.Min.minOf("date")).as("from")
                      .andOutput(AccumulatorOperators.Max.maxOf("date")).as("to");
      

      【讨论】:

      • 来自 mongo 的 [docs.mongodb.com/manual/reference/operator/aggregation/…:“根据指定的表达式将传入的文档分类为特定数量的组,称为存储桶。自动确定存储桶边界以尝试均匀分布 将文件放入指定数量的桶中。”这意味着 BucketAuto 不是存储桶的替代品,因为它无法为存储桶提供边界,这在我的情况下是强制性的。
      猜你喜欢
      • 2015-12-17
      • 2019-01-29
      • 2020-12-14
      • 2014-08-27
      • 2014-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多