Java spring-mongo-data Mongodb 查询组和投影逻辑

问题描述 投票:0回答:2

我有以下 3 条样本记录:

    {
      "_id" : "0cc5c468-2105-11ee-ad68-15d467e62by4d",
      "storeId" : "3070",
      "paymentType" : "cash",
      "total" : {"$numberDecimal": "100"}
    },
{
      "_id" : "1111111-2105-11ee-ad68-15d467e62by4d",
      "storeId" : "3070",
      "paymentType" : "cash",
      "total" : {"$numberDecimal": "100"}
    },
    {
      "_id" : "0cc5c468-2105-11ee-ad68-15d467e62by4d",
      "storeId" : "3070",
      "paymentType" : "creditCard",
      "total" : {"$numberDecimal": "50"}
    }

我正在尝试编写一些分组和投影逻辑,其中上述示例数据的所需输出应如下所示:

StoreId | Cash Payment | Card Payment | Total Amount Cash + Card
3070        200               50                250

最后一列当然可以忽略,但我需要 java 中 mongodb 的这种输出。 我已经尝试了很多事情,下面是我到目前为止没有给出所需输出的代码,它为我提供了卡支付和现金支付类型的两个单独的记录。

GroupOperation groupingLogic() {
        return group("storeId", "paymentType")
                .first("storeId").as("storeId")
                .first("paymentType").as("paymentType")
                .sum(TOTAL).as(TOTAL);
    }

我不确定如何使用 java mongodb 代码获得上面预期的输出。

请有人帮忙。

java mongodb spring-boot spring-data-mongodb
2个回答
1
投票

说明:

  1. 我们需要按 2 个参数进行分组 (
    storeId
    +
    paymentType
    ) 并对
    paymentType's
    总金额求和。
  2. 我们将每个
    total amount
    的所有
    paymentType
    storeId
    相加。
  3. 我们需要使用
    $arrayToObject
    将每个
    paymentType
    旋转到字段中。
  4. 与其他运算符一起,我们组装了预期结果。

{
   "Total Amount": NumberDecimal("250"),
   "cash": NumberDecimal("200"),
   "creditCard": NumberDecimal("50"),
   "storeId": "3070"
}

注意:

cash
creditCard
等都是动态填充的。如果任何
storeId
没有此类类型,则这些字段可能不存在。

试试这个:

db.collection.aggregate([
  {
    $group: {
      _id: {
        storeId: "$storeId",
        paymentType: "$paymentType"
      },
      total: {
        $sum: "$total"
      }
    }
  },
  {
    $group: {
      _id: "$_id.storeId",
      paymentType: {
        $push: {
          "k": "$_id.paymentType",
          "v": "$total"
        }
      },
      "total": {
        $sum: "$total"
      }
    }
  },
  {
    "$replaceWith": {
      "$arrayToObject": {
        "$concatArrays": [
          "$paymentType",
          [
            {
              "k": "storeId",
              "v": "$_id"
            },
            {
              "k": "Total Amount",
              "v": "$total"
            }
          ]
        ]
      }
    }
  }
])

Mongo游乐场

Java - 复杂的聚合管道

private static AggregationOperation replaceWith() {
    return ctx -> Document.parse("{" +
        "'$replaceWith': {" +
            "'$arrayToObject': {" +
                "..." +
            "}" +
        "}"+
    "}")
}

0
投票

如果您想对 MongoDB 集合中的一些数据进行分组和添加。以下是使用 Java 和 Spring Data MongoDB 实现此操作的方法:

如果您想按“storeId”对数据进行分组,并对不同付款类型(“现金”和“信用卡”)的金额求和。具体方法如下:

import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.query.Criteria;

// ...

GroupOperation groupingLogic() {
    return Aggregation.group("storeId")
        .sum(
            ConditionalOperators.when(Criteria.where("paymentType").is("cash")).then("$total.$numberDecimal").otherwise(0)
        ).as("cashPayment")
        .sum(
            ConditionalOperators.when(Criteria.where("paymentType").is("creditCard")).then("$total.$numberDecimal").otherwise(0)
        ).as("cardPayment")
        .sum("$total.$numberDecimal").as("totalAmountCashCard");
}

以您的格式显示。具体方法如下:

import org.springframework.data.mongodb.core.aggregation.ProjectionOperation;


ProjectionOperation projectionLogic() {
    return Aggregation.project()
        .and("storeId").as("StoreId")
        .and("cashPayment").as("Cash Payment")
        .and("cardPayment").as("Card Payment")
        .and("totalAmountCashCard").as("Total Amount Cash + Card");
}

把它们放在一起:

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class YourService {

    private final MongoTemplate mongoTemplate;

    public YourService(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    public List<YourOutputType> getGroupedData() {
        Aggregation aggregation = Aggregation.newAggregation(
            groupingLogic(),
            projectionLogic()
        );

        return mongoTemplate.aggregate(aggregation, "yourCollectionName", YourOutputType.class).getMappedResults();
    }
}

请记住将 yourCollectionName 替换为 MongoDB 集合的实际名称,将 YourOutputType 替换为与预期输出匹配的适当类。

© www.soinside.com 2019 - 2024. All rights reserved.