2014-05-05 20 views
11

Tôi đang tự hỏi làm thế nào để thực hiện một loại công đoàn trong một tổng hợp trong MongoDB. Hãy chụp ảnh tài liệu sau đây trong một bộ sưu tập (cấu trúc này là vì lợi ích của ví dụ):Thực hiện công đoàn trong mongoDB

{ 
    linkedIn: { 
    people : [ 
    { 
     name : 'Fred' 
    }, 
    { 
     name : 'Matilda' 
    } 
    ] 
    }, 
    twitter: { 
    people : [ 
    { 
     name : 'Hanna' 
    }, 
    { 
     name : 'Walter' 
    } 
    ] 
    } 
} 

Làm thế nào để làm cho một tổng hợp trả về sự kết hợp của những người trong Twitter và LinkedIn?

{ 
{ name :'Fred', source : 'LinkedIn'}, 
{ name :'Matilda', source : 'LinkedIn'}, 
{ name :'Hanna', source : 'Twitter'}, 
{ name :'Walter', source : 'Twitter'}, 
} 

Trả lời

12

có một vài phương pháp này mà bạn có thể sử dụng phương pháp aggregate cho

db.collection.aggregate([ 
    // Assign an array of constants to each document 
    { "$project": { 
     "linkedIn": 1, 
     "twitter": 1, 
     "source": { "$cond": [1, ["linkedIn", "twitter"],0 ] } 
    }}, 

    // Unwind the array 
    { "$unwind": "$source" }, 

    // Conditionally push the fields based on the matching constant 
    { "$group": { 
     "_id": "$_id", 
     "data": { "$push": { 
      "$cond": [ 
       { "$eq": [ "$source", "linkedIn" ] }, 
       { "source": "$source", "people": "$linkedIn.people" }, 
       { "source": "$source", "people": "$twitter.people" } 
      ] 
     }} 
    }}, 

    // Unwind that array 
    { "$unwind": "$data" }, 

    // Unwind the underlying people array 
    { "$unwind": "$data.people" }, 

    // Project the required fields 
    { "$project": { 
     "_id": 0, 
     "name": "$data.people.name", 
     "source": "$data.source" 
    }} 
]) 

Hoặc với một cách tiếp cận khác nhau sử dụng một số nhà khai thác từ MongoDB 2.6:

db.people.aggregate([ 
    // Unwind the "linkedIn" people 
    { "$unwind": "$linkedIn.people" }, 

    // Tag their source and re-group the array 
    { "$group": { 
     "_id": "$_id", 
     "linkedIn": { "$push": { 
      "name": "$linkedIn.people.name", 
      "source": { "$literal": "linkedIn" } 
     }}, 
     "twitter": { "$first": "$twitter" } 
    }}, 

    // Unwind the "twitter" people 
    { "$unwind": "$twitter.people" }, 

    // Tag their source and re-group the array 
    { "$group": { 
     "_id": "$_id", 
     "linkedIn": { "$first": "$linkedIn" }, 
     "twitter": { "$push": { 
      "name": "$twitter.people.name", 
      "source": { "$literal": "twitter" } 
     }} 
    }}, 

    // Merge the sets with "$setUnion" 
    { "$project": { 
     "data": { "$setUnion": [ "$twitter", "$linkedIn" ] } 
    }}, 

    // Unwind the union array 
    { "$unwind": "$data" }, 

    // Project the fields 
    { "$project": { 
     "_id": 0, 
     "name": "$data.name", 
     "source": "$data.source" 
    }} 
]) 

Và tất nhiên nếu bạn chỉ đơn giản là không quan tâm những gì các nguồn là:

db.collection.aggregate([ 
    // Union the two arrays 
    { "$project": { 
     "data": { "$setUnion": [ 
      "$linkedIn.people", 
      "$twitter.people" 
     ]} 
    }}, 

    // Unwind the union array 
    { "$unwind": "$data" }, 

    // Project the fields 
    { "$project": { 
     "_id": 0, 
     "name": "$data.name", 
    }} 

]) 
2

Không chắc nếu sử dụng tổng hợp được khuyến cáo trên một bản đồ giảm cho rằng loại hoạt động nhưng sau là làm những gì bạn đang yêu cầu cho (dunno nếu $ const có thể được sử dụng với không có vấn đề ở tất cả trong .aggregate() chức năng):

aggregate([ 
    { $project: { linkedIn: '$linkedIn', twitter: '$twitter', idx: { $const: [0,1] }}}, 
    { $unwind: '$idx' }, 
    { $group: { _id : '$_id', data: { $push: { $cond:[ {$eq:['$idx', 0]}, { source: {$const: 'LinkedIn'}, people: '$linkedIn.people' } , { source: {$const: 'Twitter'}, people: '$twitter.people' } ] }}}}, 
    { $unwind: '$data'}, 
    { $unwind: '$data.people'}, 
    { $project: { _id: 0, name: '$data.people.name', source: '$data.source' }} 
]) 
Các vấn đề liên quan