Spring

Spring Data에서 Mongo 집계 쿼리를 수행하는 방법은 무엇입니까?

기록만이살길 2022. 11. 13. 17:47
반응형

Spring Data에서 Mongo 집계 쿼리를 수행하는 방법은 무엇입니까? 물어보다

1. 질문(문제점):

Java에서 Mongo를 사용하는 것은 처음이며 이 집계 쿼리에 몇 가지 문제가 있습니다. @Query.NET Framework를 확장하는 Repository 인터페이스의 어노테이션을 사용하여 Mongo for Spring에서 몇 가지 간단한 쿼리를 수행할 수 있습니다 MongoRepository<T, ID>. Spring-Data에서 긴 집계를 수행할 때 어떤 접근 방식을 취해야 하는지 아는 것이 도움이 될 것입니다.

db.post.aggregate([
    {
      $match: {}
    },
    {
      $lookup: {
        from: "users",
        localField: "postedBy",
        foreignField: "_id",
        as: "user"
      }
    },
    {
      $group: {
        _id: {
          username: "$user.name",
          title: "$title",
          description: "$description",
          upvotes: { $size: "$upvotesBy" },
          upvotesBy: "$upvotesBy",
          isUpvoted: { $in: [req.query.userId, "$upvotesBy"] },
          isPinned: {
            $cond: {
              if: { $gte: [{ $size: "$upvotesBy" }, 3] },
              then: true,
              else: false
            }
          },
          file: "$file",
          createdAt: {
            $dateToString: {
              format: "%H:%M %d-%m-%Y",
              timezone: "+01",
              date: "$createdAt"
            }
          },
          id: "$_id"
        }
      }
    },
    { $sort: { "_id.isPinned": -1, "_id.createdAt": -1 } }
])

2. 해결방안:

이것은 오래된 쓰레드이지만 이 쓰레드를 발견한 사람이 이제 MongoRepository에서 다단계/파이프라인 집계(호출이 무엇인지 확실하지 않음)를 안전하게 수행할 수 있기를 바랍니다. 나는 또한 mongo 템플릿이 없는 mongo 저장소에서 집계의 실마리와 예를 찾는 데 어려움을 겪고 있습니다.

하지만 이제 여기 에서 말하는 Spring 문서에 따라 집계 파이프라인을 수행할 수 있습니다.

내 집계는 mongoshell에서 다음과 같습니다.

db.getCollection('SalesPo').aggregate([
    {$project: {
        month: {$month: '$poDate'},
        year: {$year: '$poDate'},
        amount: 1,
        poDate: 1
     }},
      {$match: {$and : [{year:2020} , {month:7}] 
     }}
      ,
      {$group: { 
          '_id': {
            month: {$month: '$poDate'},
            year: {$year: '$poDate'} 
          },
          totalPrice: {$sum: {$toDecimal:'$amount'}},
          }
      },
    {$project: {
        _id: 0,
        totalPrice: {$toString: '$totalPrice'}
     }}
 ])

MongoRepository에서 @Aggregation 어노테이션으로 변환하는 동안 아래와 같이 됩니다.

@Repository
public interface SalesPoRepository extends MongoRepository<SalesPo, String> {

@Aggregation(pipeline = {"{$project: {\n" +
        "        month: {$month: $poDate},\n" +
        "        year: {$year: $poDate},\n" +
        "        amount: 1,\n" +
        "        poDate: 1\n" +
        "     }}"
        ,"{$match: {$and : [{year:?0} , {month:?1}] \n" +
        "     }}"
        ,"{$group: { \n" +
        "          '_id': {\n" +
        "            month: {$month: $poDate},\n" +
        "            year: {$year: $poDate} \n" +
        "          },\n" +
        "          totalPrice: {$sum: {$toDecimal:$amount}},\n" +
        "          }\n" +
        "      }"
    ,"{$project: {\n" +
        "        _id: 0,\n" +
        "        totalPrice: {$toString: $totalPrice}\n" +
        "     }}"})
    AggregationResults<SumPrice> sumPriceThisYearMonth(Integer year, Integer month);

내 문서는 다음과 같습니다.

@Document(collection = "SalesPo")
@Data
public class SalesPo {
  @Id
  private String id;
  @JsonSerialize(using = LocalDateSerializer.class)
  private LocalDate poDate;
  private BigDecimal amount;
}

그리고 예측을 유지하기 위한 SumPrice 클래스:

@Data
public class SumPrice {
  private BigDecimal totalPrice;
}

이 답변이 mongotemplate 을 사용하지 않고 mongorepository에서 집계를 시도하는 사람에게 도움이 되기를 바랍니다 .

59697496
반응형