복붙노트

[MONGODB] 기준에 일치하는 모든 객체의 모든 배열 요소 수를 계산하여 MongoDB

MONGODB

기준에 일치하는 모든 객체의 모든 배열 요소 수를 계산하여 MongoDB

이 같은 객체에 대한 활동의 ​​로그 인 컬렉션이 :

{
    "_id" : ObjectId("55e3fd1d7cb5ac9a458b4567"),
    "object_id" : "1",
    "activity" : [ 
        {
            "action" : "test_action",
            "time" : ISODate("2015-08-31T00:00:00.000Z")
        },
        {
            "action" : "test_action",
            "time" : ISODate("2015-08-31T00:00:22.000Z")
        }
    ]
}

{
    "_id" : ObjectId("55e3fd127cb5ac77478b4567"),
    "object_id" : "2",
    "activity" : [ 
        {
            "action" : "test_action",
            "time" : ISODate("2015-08-31T00:00:00.000Z")
        }
    ]
}

{
    "_id" : ObjectId("55e3fd0f7cb5ac9f458b4567"),
    "object_id" : "1",
    "activity" : [ 
        {
            "action" : "test_action",
            "time" : ISODate("2015-08-30T00:00:00.000Z")
        }
    ]
}

내가 쿼리 다음을 수행하는 경우 :

db.objects.find({
    "createddate": {$gte : ISODate("2015-08-30T00:00:00.000Z")},
    "activity.action" : "test_action"}
    }).count()

그것은 (세트 3) "test_action"를 포함하는 문서의 개수를 반환한다,하지만 난 (세트 4) 모든 test_actions의 수를 얻을 필요가있다. 어떻게 그렇게 할 수 있습니까?

해결법

  1. ==============================

    1.이 작업을 수행하는 가장 "성능이 좋은"방법은 언 와인드 전부 $를 생략하고 단순히 $ 그룹을 계산하는 것입니다. 기본적으로 "필터"배열은 $ 합 결과의 $ 크기를 얻을 :

    이 작업을 수행하는 가장 "성능이 좋은"방법은 언 와인드 전부 $를 생략하고 단순히 $ 그룹을 계산하는 것입니다. 기본적으로 "필터"배열은 $ 합 결과의 $ 크기를 얻을 :

    db.objects.aggregate([
        { "$match": {
            "createddate": {
                "$gte": ISODate("2015-08-30T00:00:00.000Z")
            },
            "activity.action": "test_action"
        }},
        { "$group": {
            "_id": null,
            "count": {
                "$sum": {
                    "$size": {
                        "$setDifference": [
                            { "$map": {
                                "input": "$activity",
                                "as": "el",
                                "in": {
                                    "$cond": [ 
                                        { "$eq": [ "$$el.action", "test_action" ] },
                                        "$$el",
                                        false
                                    ]
                                }               
                            }},
                            [false]
                        ]
                    }
                }
            }
        }}
    ])
    

    MongoDB의 향후 릴리스는이 훨씬 더 간단하게 $ 필터를해야합니다 :

    db.objects.aggregate([
        { "$match": {
            "createddate": {
                "$gte": ISODate("2015-08-30T00:00:00.000Z")
            },
            "activity.action": "test_action"
        }},
        { "$group": {
            "_id": null,
            "count": {
                "$sum": {
                    "$size": {
                        "$filter": {
                            "input": "$activity",
                            "as": "el",
                            "cond": {
                                "$eq": [ "$$el.action", "test_action" ]
                            }
                        }
                    }
                }
            }
        }}
    ])
    

    $ 언 와인드 원인에게 문서를 사용하면-정상화를 해제하고 효과적으로 배열 항목마다 복사본을 생성합니다. 가능하다면 당신은 종종 극단적 인 비용 때문에이를 방지해야한다. 필터링 및 문서에 따라 배열 항목을 계산하는 것은 비교하면 훨씬 빠릅니다. 같은 간단한의 $ 일치와 $ 그룹 파이프 라인은 여러 단계에 비해입니다.

  2. ==============================

    2.당신은 집계를 사용하여 수행 할 수 있습니다 :

    당신은 집계를 사용하여 수행 할 수 있습니다 :

    db.objects.aggregate([
        {$match: {"createddate": {$gte : ISODate("2015-08-30T00:00:00.000Z")}, {"activity.action" : "test_action"}}},
        {$unwind: "$activity"},
        {$match: {"activity.action" : "test_action"}}},
        {$group: {_id: null, count: {$sum: 1}}}
    ])
    

    이 같은 결과를 생성합니다 :

    {
        count: 4
    }
    
  3. from https://stackoverflow.com/questions/32305897/mongodb-count-all-array-elements-in-all-objects-matching-by-criteria by cc-by-sa and MIT license