programing

그룹화 및 조건 포함 개수

newstyles 2023. 6. 23. 21:48

그룹화 및 조건 포함 개수

문서 집합을 그룹화하고 값을 기준으로 카운트하려고 합니다.

{ item: "abc1", value: 1 }
{ item: "abc1", value: 1 }
{ item: "abc1", value: 11 }
{ item: "xyz1", value: 2 }

저는 다음과 같이 그룹화하고 싶습니다.item그리고 그 대가로 몇 번인지 세어보세요.value보다 큼10그리고 몇 배나 작은지:

{ item: "abc1", countSmaller: 2, countBigger: 1 }
{ item: "xyz1", countSmaller: 1, countBigger: 0 }

당신에게 필요한 것은 집계 프레임워크의 운영자입니다.원하는 것을 얻을 수 있는 한 가지 방법은 다음과 같습니다.

db.foo.aggregate([
    {
        $project: {
            item: 1,
            lessThan10: {  // Set to 1 if value < 10
                $cond: [ { $lt: ["$value", 10 ] }, 1, 0]
            },
            moreThan10: {  // Set to 1 if value > 10
                $cond: [ { $gt: [ "$value", 10 ] }, 1, 0]
            }
        }
    },
    {
        $group: {
            _id: "$item",
            countSmaller: { $sum: "$lessThan10" },
            countBigger: { $sum: "$moreThan10" }
        }
    }
])

참고: 저는 다음과 같이 가정했습니다.value문자열이 아닌 숫자로 변환합니다.

출력:

{
        "result" : [
                {
                        "_id" : "xyz1",
                        "countSmaller" : 1,
                        "countBigger" : 0
                },
                {
                        "_id" : "abc1",
                        "countSmaller" : 2,
                        "countBigger" : 2
                }
        ],
        "ok" : 1
}  

연산자를 사용해야 합니다.여기서0값이 다음보다 작습니다.10그리고.1보다 큰 값10이것은 정확하게 예상되는 출력을 제공하지 않습니다.아마도 누군가가 더 나은 답변을 게시할 것입니다.

db.collection.aggregate(
    [
        {
            "$project": 
                {
                    "item": 1, 
                    "value": 
                        {
                            "$cond": [ { "$gt": [ "$value", 10 ] }, 1, 0 ] 
                        }
                 }
         }, 
         {
             "$group": 
                 {
                     "_id": { "item": "$item", "value": "$value" },                       
                     "count": { "$sum": 1 }
                 }
         }, 
         {
             "$group": 
                 { 
                     "_id": "$_id.item", 
                     "stat": { "$push": { "value": "$_id.value", "count": "$count" }}
                 }
          }
    ]
)

출력:

{
        "_id" : "abc1",
        "stat" : [
                {
                        "value" : 1,
                        "count" : 2
                },
                {
                        "value" : 0,
                        "count" : 2
                }
        ]
}
{ "_id" : "xyz1", "stat" : [ { "value" : 0, "count" : 1 } ] }

값을 다음으로 변환해야 합니다.integer또는float

이 시나리오에 대한 Java 코드를 찾는 사용자가 있는 경우(필요에 따라 필드가 업데이트됨

Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.project("environment").and("success").applyCondition(ConditionalOperators.when(Criteria.where("deploymentStatus").is("SUCCESS"))
                        .then(1)
                        .otherwise(0)).and("failed").applyCondition(ConditionalOperators.when(Criteria.where("deploymentStatus").is("FAILURE"))
                        .then(1)
                        .otherwise(0)),
                Aggregation.group("environment").sum("success").as("success").sum("failed").as("failed"));

$group 단계의 조건에 따라 데이터를 계산하기 위해 MongoDb 버전 5.0에서 변경된 "$accumulator" 연산자를 사용할 수 있습니다.

따라서 귀하의 요구 사항에 따라 이 집계 단계를 사용하여 구현할 수 있습니다.

db.products.aggregate([
  {
    $group: {
      _id: "$item",
      totalCounts: { $sum: 1 },
      countsMeta: {
        $accumulator: {
          init: function () {
            // Set the initial state
            return { countSmaller: 0, countBigger: 0 };
          },
          accumulate: function (state, value) {
            // Define how to update the state
            return value < 10
              ? { ...state, countSmaller: state.countSmaller + 1 }
              : { ...state, countBigger: state.countBigger + 1 };
          },
          accumulateArgs: ["$value"], // Pass the desired argument to the accumulate function
          merge: function (state1, state2) {
            /* 
                Executed when the operator performs a merge,
                Merge may happen in two cases : 
                 1). $accumulator is run on a sharded cluster. The operator needs to merge the 
                     results from each shard to obtain the final result.
                 2). A single $accumulator operation exceeds its specified memory limit. 
                     If you specify the allowDiskUse option, the operator stores the 
                     in-progress operation on disk and finishes the operation in memory. 
                     Once the operation finishes, the results from disk and memory are 
                     merged together using the merge function.
                The merge function always merges two states at a time. In the event that more 
                than two states must be merged, the resulting merge of two states is merged 
                with a single state. This process repeats until all states are merged.     
            */

            return {
              countSmaller: state1.countSmaller + state2.countSmaller,
              countBigger: state1.countBigger + state2.countBigger,
            };
          },
          finalize: function (state) {
            // After collecting the results from all documents,
            return state;
          },
          lang: "js",
        },
      },
    },
  },
]);

이 실행은 다음과 같은 결과를 제공합니다.

Result Image Snapshow

스테이지 및 조작자에 대한 자세한 내용은 다음 링크를 참조하십시오.

https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator/

이것이 당신이나 다른 누군가에게 도움이 되기를 바랍니다.감사합니다!

해피 코딩 :-)

아난드의 대답과 매우 유사하지만 한 단계로:

$group: {
    _id: "$item",
    countSmaller: { $sum: {$cond: [ { $lt: ["$value", 10 ] }, 1, 0]} },
    countBigger: { $sum: {$cond: [ { $gt: [ "$value", 10 ] }, 1, 0]} }
}

언급URL : https://stackoverflow.com/questions/30169115/group-and-count-with-condition