2013-07-01 24 views
3

相關問題是Efficiently convert rows to columns in sql server。但是答案是針對SQL的。將行轉換爲MongoDB中的列

我想要相同的結果,即將行轉換爲列,而不在MongoDB中彙總任何內容(截至目前爲止)。

集合看起來如下所示。這是Facebook的頁面屬性統計:

 

timestamp | propName | propValue 
-------------------------------- 
1371798000000 | page_fans | 100 
-------------------------------- 
1371798000000 | page_posts | 50 
-------------------------------- 
1371798000000 | page_stories | 25 
-------------------------------- 

我需要回答如下:

 
timestamp | page_fans | page_posts | page_stories 
-------------------------------- 
1371798000000 | 100 | 50 | 25 
-------------------------------- 

的列名是預先確定的。他們不必動態生成。但問題是如何在MongoDB中實現這一點。

我認爲聚合對此目的沒有用處。我需要使用MapReduce嗎?但在這種情況下,我沒有什麼可以減少的我猜?那麼另一個選擇就是可以在代碼中獲取這些值並在編程語言中進行操作。 Java

任何見解都會有所幫助。提前致謝 :)!!!

EDIT(基於輸入從Schaliasos):

輸入JSON:

{ 
     "_id" : ObjectId("51cd366644aeac654ecf8f75"), 
     "name" : "page_storytellers", 
     "pageId" : "512f993a44ae78b14a9adb85", 
     "timestamp" : NumberLong("1371798000000"), 
     "value" : NumberLong(30871), 
     "provider" : "Facebook" 
} 
{ 
     "_id" : ObjectId("51cd366644aeac654ecf8f76"), 
     "name" : "page_fans", 
     "pageId" : "512f993a44ae78b14a9adb85", 
     "timestamp" : NumberLong("1371798000000"), 
     "value" : NumberLong(1291509), 
     "provider" : "Facebook" 
} 
{ 
     "_id" : ObjectId("51cd366644aeac654ecf8f77"), 
     "name" : "page_fan_adds", 
     "pageId" : "512f993a44ae78b14a9adb85", 
     "timestamp" : NumberLong("1371798000000"), 
     "value" : NumberLong(2829), 
     "provider" : "Facebook" 
} 

期望輸出JSON:

{ 
     "timestamp" : NumberLong("1371798000000"), 
     "provider" : "Facebook", 
     "page_storytellers" : NumberLong(30871), 
     "page_fans" : NumberLong("1371798000000"), 
     "page_fan_adds" : NumberLong("1371798000000") 
} 
+1

首先,MongoDB中有一個JSON格式的文檔。張貼您擁有的json和您想要返回的json,以便我們更好地理解它。其次,你爲什麼要這樣? – Schaliasos

+0

這是在客戶端完成的最好的事情,我不會使用下面的答案來做到這一點,直到你遇到這樣的查詢縮放問題時,它不會很長。 – Sammaye

回答

7

我做了這樣的事情使用聚集。這可以幫助嗎?

db.foo.insert({ timestamp: '1371798000000', propName: 'page_fans', propValue: 100}) 
db.foo.insert({ timestamp: '1371798000000', propName: 'page_posts', propValue: 25}) 
db.foo.insert({ timestamp: '1371798000000', propName: 'page_stories', propValue: 50}) 

db.foo.aggregate({ $group: { _id: '$timestamp', result: { $push: { 'propName': '$propName', 'propValue': '$propValue' } }}}) 

{ 
    "result" : [ 
     { 
      "_id" : "1371798000000", 
      "result" : [ 
       { 
        "propName" : "page_fans", 
        "propValue" : 100 
       }, 
       { 
        "propName" : "page_posts", 
        "propValue" : 50 
       }, 
       { 
        "propName" : "page_stories", 
        "propValue" : 25 
       } 
      ] 
     } 
    ], 
    "ok" : 1 
} 

您可能希望使用$sum運算符。請參閱here

+1

看起來很有趣。這是我的想法之一,但問題是我需要根據特定屬性及其值創建日常圖表。獲得像這樣的結果仍然需要一些我想避免的代碼中的額外處理。我會看到,但如果我能適應這個地方。感謝回覆。 – mayur

+0

您歡迎。如果你認爲這不能完全回答你的問題,請考慮至少投票;)祝你好運。 –

+0

對不起,現在就這樣做了。我想我可以通過在服務器端服務中獲得輸出和格式並將結果以可用於製圖的格式返回給客戶端來利用以上。 如果有人有更好的選擇提供,會等待。再次感謝!!! – mayur

0

現在,您可以利用新彙總operator $arrayToObject來轉換MongoDB密鑰。該操作符在MongoDB v3.4中可用。4+

例如,給定的示例性數據:

db.foo.insert({ provider: "Facebook", timestamp: '1371798000000', name: 'page_storytellers', value: 20871}) 
db.foo.insert({ provider: "Facebook", timestamp: '1371798000000', name: 'page_fans', value: 1291509}) 
db.foo.insert({ provider: "Facebook", timestamp: '1371798000000', name: 'page_fan_adds', value: 2829}) 
db.foo.insert({ provider: "Google", timestamp: '1371798000000', name: 'page_fan_adds', value: 1000}) 

可以Aggregation Pipeline下面利用:

db.foo.aggregate([ 
    {$group: 
    {_id:{provider:"$provider", timestamp:"$timestamp"}, 
     items:{$addToSet:{name:"$name",value:"$value"}}} 
    }, 
    {$project: 
    {tmp:{$arrayToObject: 
     {$zip:{inputs:["$items.name", "$items.value"]}}}} 
    }, 
    {$addFields: 
    {"tmp.provider":"$_id.provider", 
     "tmp.timestamp":"$_id.timestamp"} 
    }, 
    {$replaceRoot:{newRoot:"$tmp"} 
    } 
]); 

輸出將是:

{ 
    "page_fan_adds": 1000, 
    "provider": "Google", 
    "timestamp": "1371798000000" 
}, 
{ 
    "page_fan_adds": 2829, 
    "page_fans": 1291509, 
    "page_storytellers": 20871, 
    "provider": "Facebook", 
    "timestamp": "1371798000000" 
} 

參見$group$project, $addFields$zip, 和$replaceRoot

0

示例數據:

db.products.insertMany([ 
 
    { 
 
     "_id":"m1", 
 
     "model":"Model 1", 
 
     "size": "3.5", 
 
     "grade":"B", 
 
     "quantity":1.0 
 
    }, 
 
    { 
 
     "_id":"m2", 
 
     "model":"Model 1", 
 
     "size": "3.5", 
 
     "grade":"A", 
 
     "quantity":2.0 
 
    }, 
 
    { 
 
     "_id":"m3", 
 
     "model":"Model 2", 
 
     "size": "3.5", 
 
     "grade":"A", 
 
     "quantity":3.0 
 
    }, 
 
    { 
 
     "_id":"m4", 
 
     "model":"Model 2", 
 
     "size": "3.5", 
 
     "grade":"A", 
 
     "quantity":4.0 
 
    }, 
 
    { 
 
     "_id":"m5", 
 
     "model":"Model 2", 
 
     "size": "5.5", 
 
     "grade":"C", 
 
     "quantity":3.0 
 
    }, 
 
    { 
 
     "_id":"m6", 
 
     "model":"Model 3", 
 
     "size": "5.5", 
 
     "grade":"B", 
 
     "quantity":10.0 
 
    } 
 
])

查詢:

db.products.aggregate([ 
 
{ $group: { _id: { item: { model: "$model", grade: "$grade" } }, total: { $sum: "$quantity" } } }, 
 
{ $project: { _id: 0, grades: 1, item: "$_id.item", total: 1 } }, 
 
{ $group: { _id: { item: {model: "$item.model"} }, grades: { $addToSet: { name: "$item.grade", sum: "$total" } } } }, 
 
{ $project: { _id: 0, item: "$_id.item", grades: 1 } }, 
 
{ $sort : { item: 1 } }, 
 
]);

結果:

所有的

/* 1 */ 
 
{ 
 
    "grades" : [ 
 
     { 
 
      "name" : "A", 
 
      "sum" : 2.0 
 
     }, 
 
     { 
 
      "name" : "B", 
 
      "sum" : 1.0 
 
     } 
 
    ], 
 
    "item" : { 
 
     "model" : "Model 1" 
 
    } 
 
} 
 

 
/* 2 */ 
 
{ 
 
    "grades" : [ 
 
     { 
 
      "name" : "A", 
 
      "sum" : 7.0 
 
     }, 
 
     { 
 
      "name" : "C", 
 
      "sum" : 3.0 
 
     } 
 
    ], 
 
    "item" : { 
 
     "model" : "Model 2" 
 
    } 
 
} 
 

 
/* 3 */ 
 
{ 
 
    "grades" : [ 
 
     { 
 
      "name" : "B", 
 
      "sum" : 10.0 
 
     } 
 
    ], 
 
    "item" : { 
 
     "model" : "Model 3" 
 
    } 
 
}