복붙노트

[MONGODB] 이름을 일치하는 배열 요소의 MongoDB를 2.1 집계 프레임 워크 합

MONGODB

이름을 일치하는 배열 요소의 MongoDB를 2.1 집계 프레임 워크 합

이것은 내가 다른 요소와 일치 할 필요는 배열에서 일련의 데이터를 추가하는 가장 좋은 방법에 대한 질문입니다. 나는 2.2 집계 프레임 워크를 사용하려고 해요 그리고 내가 간단한 그룹과이 작업을 수행 할 수있는 가능성이 있습니다.

나는이 같은 출력을 얻으려고 문서의 주어진 집합에 대한 그래서;

{
    "result" : [
            {
                "_id" : null,
                "numberOf": 2,
                "Sales" : 468000,
                "profit" : 246246,
            }
    ],
    "ok" : 1
}

지금, 나는 원래 명명 된 속성, 예에 할당 된 값을 포함하는 문서의 목록을했다;

[
{
    _id : 1,
    finance: {
        sales: 234000,
        profit: 123123,
    }
}
,
{
    _id : 2,
    finance: {
        sales: 234000,
        profit: 123123,
    }
}
]

이 합계 쉽게 충분하지만, 구조는 다른 이유로 작동하지 않았다. 예를 들어, "금융"와 같은 5 월 다른 열이있다 나는 이런 구조로 변환 할 필요가 그래서 나는, 인덱스의 수천을 만들지 않고 인덱스 그들에게 할 수 있도록하려면,

[
{
    _id : 1,
    finance: [
        {
            "k": "sales",
            "v": {
                "description":"sales over the year",
                v: 234000,
            }
        },
        {
            "k": "profit",
            "v": {
                "description":"money made from sales",
                v: 123123,
            }
        }
    ]
}
,
{
    _id : 2,
    finance: [
        {
            "k": "sales",
            "v": {
                "description":"sales over the year",
                v: 234000,
            }
        },
        {
            "k": "profit",
            "v": {
                "description": "money made from sales",
                v: 123123,
            }
        }
    ]
}
]

내가 원한다면 나는 인덱스 finance.k을 할 수 있지만, 그때는 특정 키와 일치하는 모든 숫자를 추가 할 수 집계 쿼리를 작성하기 위해 사투를 벌인거야. 이것은 내가 원래 명명 된 속성에 들어갑니다 이유 있었다, 그러나 이것은 정말 "K"라벨의 수천이있다, 이에 상황에서 작업 할 필요가있다.

사람이 새로운 프레임 워크를 사용하는 집계 쿼리를 작성하는 방법을 알고 있나요? 나는이 시도했다;

db.projects.aggregate([
    {
        $match: {
            // QUERY
            $and: [
                // main query
                {},
            ]
        }
    },
    {
        $group: {
            _id: null,
            "numberOf": { $sum: 1 },
            "sales":    { $sum: "$finance.v.v" },
            "profit":   { $sum: "$finance.v.v" },
        }
    },
])

하지만 난 얻을;

{
    "errmsg" : "exception: can't convert from BSON type Array to double",
    "code" : 16005,
    "ok" : 0
}

** 여분의 명성을 위해, 나는뿐만 아니라 맵리 듀스 쿼리에서이 작업을 수행 할 수 있도록해야합니다.

해결법

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

    1.당신은 매출과 이익과 당신이 당신의 키 / 값 쌍의 표현에 저장 될 수있는 다른 값을 얻을 수있는 통합 프레임 워크를 사용할 수 있습니다.

    당신은 매출과 이익과 당신이 당신의 키 / 값 쌍의 표현에 저장 될 수있는 다른 값을 얻을 수있는 통합 프레임 워크를 사용할 수 있습니다.

    귀하의 예를 들어 데이터의 경우 :

    var pipeline = [
        {
            "$unwind" : "$finance"
        },
        {
            "$group" : {
                "_id" : "$finance.k",
                "numberOf" : {
                    "$sum" : 1
                },
                "total" : {
                    "$sum" : "$finance.v.v"
                }
            }
        }
    ]
    
    R = db.tb.aggregate( pipeline );
    printjson(R);
    {
            "result" : [
                {
                    "_id" : "profit",
                    "numberOf" : 2,
                    "total" : 246246
                },
                {
                    "_id" : "sales",
                    "numberOf" : 2,
                    "total" : 468000
                }
            ],
            "ok" : 1
    }
    

    추가 K / V 쌍을 경우에만 [ "판매", "이익"]에 K 값을 통과 일치하는 항목을 추가 할 수 있습니다.

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

    2.. 당신은 $ 언 와인드 "단일 집계 명령에 매출의 합과 이익 쿼리 자체가 쉬운 것을 감안할을 얻을 수 있다는 것을 의미 할 배열의 값을 탈옥 '를 사용해야합니다 :

    . 당신은 $ 언 와인드 "단일 집계 명령에 매출의 합과 이익 쿼리 자체가 쉬운 것을 감안할을 얻을 수 있다는 것을 의미 할 배열의 값을 탈옥 '를 사용해야합니다 :

    var pipeline = [ 
            {"$unwind": "$finance" } ,
            {"$match": {"finance.k": "sales"} },
            { $group: 
                { _id: null,
                    numberOf: { "$sum": 1 },
                    sales: {"$sum": "$finance.v.v" }
                }
            }
        ];
    
    R = db.tb.aggregate( pipeline );
    printjson(R);
    
    {
            "result" : [
                    {
                            "_id" : null,
                            "numberOf" : 2,
                            "sales" : 236340
                    }
            ],
            "ok" : 1
    }
    

    당신은 단지 "$ 일치"연산자에 "판매"에 대한 "이익"대체, 이익 유사한 쿼리를 실행할 수 있습니다.

    아, 그리고 여기지도입니다 / 예를 줄일 :

    map = function() {
        var ret = { sales: 0.0 , profit: 0.0, count: 1 };
    
        // iterate over 'finance[]' array
        this.finance.forEach( function (i) { 
            if ( i.k == "sales" ) ret.sales =  i.v.v ;
            if ( i.k == "profit" ) ret.profit =  i.v.v ;
        } );
    
        emit( 1, ret );
    }
    
    reduce = function(key, values) {
        var ret = { sales: 0.0 , profit: 0.0, count: 0 };
    
        values.forEach(function(v) {
            ret.sales += v.sales;
            ret.profit += v.profit;
            ret.count += v.count;
        });
    
        return ret;
        };
    //
    // run map/reduce
    //
    res = SOURCE.mapReduce( map, reduce );
    
  3. from https://stackoverflow.com/questions/12162681/mongodb-2-1-aggregate-framework-sum-of-array-elements-matching-a-name by cc-by-sa and MIT license