복붙노트

[MONGODB] 몽고와 모든 문서에서 배열 발생을 계산

MONGODB

몽고와 모든 문서에서 배열 발생을 계산

임 같은 어떤 모습 문서의 컬렉션 풀 데이터하려고 :

[
  {
    name: 'john',
    sex: 'male',
    hobbies: ['football', 'tennis', 'swimming']
  },
  {
    name: 'betty'
    sex: 'female',
    hobbies: ['football', 'tennis']
  },
  {
    name: 'frank'
    sex: 'male',
    hobbies: ['football', 'tennis']
  } 
]

내가 가장 일반적인 취미를 계산, 성별 데이터 분할을 제시 집계 프레임 워크를 사용하는 것을 시도하고있다. 결과는 같을 것이다.

{ _id: 'male', 
  total: 2, 
  hobbies: {
    football: 2,
    tennis: 2,
    swimming: 1
  } 
},
{ _id: 'female', 
  total: 1, 
    hobbies: {
      football: 1,
      tennis: 1
    } 
}

지금까지 각 성별의 총을 얻을 수 있습니다,하지만 난 확실히 내가 아마도 취미 배열의 합계를 얻기 위해 언 와인드 사용할 수있는 방법이 아니에요.

지금까지 내 코드 :

collection.aggregate([
        { 
            $group: { 
                _id: '$sex', 
                total: { $sum: 1 }
            }
        }
    ])

해결법

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

    1.개인적으로 나는 결과에 키의 이름으로 "데이터를"변화의 큰 팬이 아니다. 작업의 종류 중 하나를 지원하지 않습니다으로 집계 프레임 워크 원칙은 aggree 경향이있다.

    개인적으로 나는 결과에 키의 이름으로 "데이터를"변화의 큰 팬이 아니다. 작업의 종류 중 하나를 지원하지 않습니다으로 집계 프레임 워크 원칙은 aggree 경향이있다.

    그래서 개인적인 취향은 "데이터"로 "데이터"를 유지하고 처리 된 출력이 실제로 더 이상의 논리 일관된 객체 설계하는 것을 동의하는 것입니다 :

    db.people.aggregate([
        { "$group": {
            "_id": "$sex",
            "hobbies": { "$push": "$hobbies" },
            "total": { "$sum": 1 }
        }},
        { "$unwind": "$hobbies" },
        { "$unwind": "$hobbies" },
        { "$group": {
            "_id": {
                "sex": "$_id",
                "hobby": "$hobbies"
            },
            "total": { "$first": "$total" },
            "hobbyCount": { "$sum": 1 }
        }},
        { "$group": {
            "_id": "$_id.sex",
            "total": { "$first": "$total" },
            "hobbies": {
                "$push": { "name": "$_id.hobby", "count": "$hobbyCount" }
            }
        }}
    ])
    

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

    [
        {
                "_id" : "female",
                "total" : 1,
                "hobbies" : [
                    {
                        "name" : "tennis",
                        "count" : 1
                    },
                    {
                        "name" : "football",
                        "count" : 1
                    }
                ]
        },
        {
            "_id" : "male",
            "total" : 2,
            "hobbies" : [
                {
                    "name" : "swimming",
                    "count" : 1
                },
                {
                    "name" : "tennis",
                    "count" : 2
                },
                {
                    "name" : "football",
                    "count" : 2
                }
            ]
        }
    ]
    

    초기 $ 그룹은 "섹스"당 계산을 수행하고 배열의 배열에 취미를 스택 그래서. 그런 다음 해제 정상화 당신이 $ 언 와인드 두 번 단일 항목을 얻기 위해, 각 성에서 취미 당 합계를 얻을 결국 혼자 각각 섹스 배열을 재편성 $ 그룹.

    그것은 프로세스에 쉽게 일관성 있고 유기적 인 구조를 가지고, 동일한 데이터, 그리고 MongoDB를하고 통합 프레임 워크는이 출력을 생성에 매우 행복했다.

    당신이 정말로 키의 이름으로 데이터를 변환해야합니다 (그리고 디자인에 따라 좋은 패턴 아니므로 나는 아직도 당신이하지 않는 것이 좋습니다) 후 최종 상태에서 이러한 어트 변환을하고, 경우 클라이언트 코드 처리를위한 매우 간단하다. 쉘에 적합한 기본 자바 스크립트 예를 들어 :

    var out = db.people.aggregate([
        { "$group": {
            "_id": "$sex",
            "hobbies": { "$push": "$hobbies" },
            "total": { "$sum": 1 }
        }},
        { "$unwind": "$hobbies" },
        { "$unwind": "$hobbies" },
        { "$group": {
            "_id": {
                "sex": "$_id",
                "hobby": "$hobbies"
            },
            "total": { "$first": "$total" },
            "hobbyCount": { "$sum": 1 }
        }},
        { "$group": {
            "_id": "$_id.sex",
            "total": { "$first": "$total" },
            "hobbies": {
                "$push": { "name": "$_id.hobby", "count": "$hobbyCount" }
            }
        }}
    ]).toArray();
    
    out.forEach(function(doc) {
        var obj = {};
        doc.hobbies.sort(function(a,b) { return a.count < b.count });
        doc.hobbies.forEach(function(hobby) {
            obj[hobby.name] = hobby.count;
        });
        doc.hobbies = obj;
        printjson(doc);
    });
    

    그리고 당신은 기본적으로 정말 정말 어쨌든 서버에서 필요한 집계 함수가 아닌 원하는 출력 형태로 각 커서 결과를 처리하고 있습니다 :

    {
        "_id" : "female",
        "total" : 1,
        "hobbies" : {
            "tennis" : 1,
            "football" : 1
        }
    }
    {
        "_id" : "male",
        "total" : 2,
        "hobbies" : {
            "tennis" : 2,
            "football" : 2,
            "swimming" : 1
        }
    }
    

    그 또한 매우 사소한 있어야 할 곳에 필요에 따라 기본적으로 그냥 같은 논리대로, 변환 커서 결과의 스트림 처리에 조작의 종류를 구현합니다.

    반면에, 당신은 항상 대신 맵리 듀스를 사용하여 서버에있는 모든 조작을 구현할 수 있습니다 :

    db.people.mapReduce(
        function() {
            emit(
                this.sex,
                { 
                    "total": 1,
                    "hobbies": this.hobbies.map(function(key) {
                        return { "name": key, "count": 1 };
                    })
                }
            );
        },
        function(key,values) {
            var obj  = {},
                reduced = {
                    "total": 0,
                    "hobbies": []
                };
    
            values.forEach(function(value) {
                reduced.total += value.total;
                value.hobbies.forEach(function(hobby) {
                    if ( !obj.hasOwnProperty(hobby.name) )
                        obj[hobby.name] = 0;
                    obj[hobby.name] += hobby.count;
                });
            });
    
            reduced.hobbies = Object.keys(obj).map(function(key) {
                return { "name": key, "count": obj[key] };
            }).sort(function(a,b) {
                return a.count < b.count;
            });
    
            return reduced;
        },
        { 
            "out": { "inline": 1 },
            "finalize": function(key,value) {
                var obj = {};
                value.hobbies.forEach(function(hobby) {
                    obj[hobby.name] = hobby.count;
                });
                value.hobbies = obj;
                return value;
            }
        }
    )
    

    맵리 듀스를 갖는 경우는 출력 만의 독특한 스타일은, 그러나 통합 프레임 워크가 할 수있는 가능성이 효율적하지 않을 경우 동일한 원칙, 축적 및 조작에 사용됩니다 :

       "results" : [
            {
                "_id" : "female",
                "value" : {
                    "total" : 1,
                    "hobbies" : {
                        "football" : 1,
                        "tennis" : 1
                    }
                }
            },
            {
                "_id" : "male",
                "value" : {
                    "total" : 2,
                    "hobbies" : {
                        "football" : 2,
                        "tennis" : 2,
                        "swimming" : 1
                    }
                }
            }
        ]
    

    하루의 끝에서, 나는 아직도 처리의 첫 번째 양식도 키의 이름에 데이터 포인트를 변환하는 시도하지 않고, 가장 효율적이고 내 마음 데이터 출력의 가장 자연스럽고 일관된 작업을 제공 말한다. 그것은 그 패턴 다음 사항을 고려하는 것이 가장,하지만 당신이 정말로해야하는 경우, 다음 처리에 대한 다양한 접근 방식에서 원하는 형태로 결과를 조작하는 방법이 있습니다.

  2. from https://stackoverflow.com/questions/34089056/count-array-occurrences-across-all-documents-with-mongo by cc-by-sa and MIT license