2013-04-20 54 views
0

我正在使用動態表單構建器將值存儲到mongo中。這意味着這些字段在運行時定義。在mongo中投影子查詢

現在我試圖讓用戶建立一個動態的數據網格視圖,以便他們可以一目瞭然地選擇他們希望看到的字段。因此,我需要投影存儲在集合項目中的字段子集。

這裏是2個記錄的集合中的例子

{ 
"_id": { 
    "$oid": "511ff0a8521e66d41b0d35d6" 
}, 
"FormID": { 
    "$uuid": "413ba627-94bf-0ca7-49b3-9ca2a1a3e9b5" 
}, 
"ResultID": { 
    "$uuid": "45f455ae-8486-aaa9-b97a-e480bfdf3db4" 
}, 
"FieldValues": [ 
    { 
     "FieldID": "first name", 
     "FieldValue": "John" 
    }, 
    { 
     "FieldID": "last name", 
     "FieldValue": "smith" 
    }, 
    { 
     "FieldID": "school", 
     "FieldValue": "high school" 
    }, 
    { 
     "FieldID": "favorite subject", 
     "FieldValue": "math" 
    }, 

] 
}, 

{ 
"_id": { 
    "$oid": "511ff0a8521e66d41b0d35d7" 
}, 
"FormID": { 
    "$uuid": "413ba627-94bf-0ca7-49b3-9ca2a1a3e9b5" 
}, 
"ResultID": { 
    "$uuid": "45f455ae-8486-aaa9-b97a-e480bfdf3db5" 
}, 
"FieldValues": [ 
    { 
     "FieldID": "first name", 
     "FieldValue": "sarah" 
    }, 
    { 
     "FieldID": "last name", 
     "FieldValue": "smith" 
    }, 
    { 
     "FieldID": "school", 
     "FieldValue": "high school" 
    }, 
    { 
     "FieldID": "favorite subject", 
     "FieldValue": "english" 
    }, 

] 
}, 

比方說,我想對項目結果ID,名字,姓

在SQL - 我會在已定義FieldValues它自己的表,並且我會對ResultId =(父結果id)和FieldID =「first name」的Field值進行子查詢,然後對「last name」進行另一個子查詢等,以平滑結果。

我一直想弄清楚如何用mongo做到這一點。我能夠找到$ slice操作符,但只能讓你獲得一組連續的數組元素。

我不想獲取整個文檔的原因是,在某些情況下,我的客戶已經定義了400多個字段進行跟蹤。反序列化甚至200行上的所有內容可能意味着100MB數據通過網絡傳輸並反序列化(緩慢)。

任何意見/建議,將不勝感激

+0

好奇你爲什麼用mapreduce標記問題? – 2013-04-21 13:13:41

+0

我認爲有一種方法可以在mapreduce中做到這一點,因此遵循該標籤的人可能會提供幫助。但我知道彙總框架也是一種可能性 – apexdodge 2013-04-22 20:16:41

回答

2

您可以構建一個合適的聚合框架語法返回正是你想要的。它可能速度不夠快,但它會返回所需的確切格式,而不會拖動整個文檔。爲了讓速度更快,我假設你將避免在整個集合中運行它,因爲管道的第一階段是僅選擇相關文檔子集的一些{$match}(並且該標準應該被編入索引)。

在字段first namelast name的兩個示例文檔上使用以下流水線階段,只返回_id和那些字段。對於一組給定的字段ID,您可以以編程方式生成此管道。

unwind = { "$unwind" : "$FieldValues" }; 

match = { "$match" : { 
     "FieldValues.FieldID" : { 
      "$in" : [ 
       "first name", 
       "last name" 
      ] 
     } 
    } 
}; 

proj = { "$project" : { 
     "first name" : { 
      "$cond" : [ 
       { 
        "$eq" : [ 
         "first name", 
         "$FieldValues.FieldID" 
        ] 
       }, 
       "$FieldValues.FieldValue", 
       " skip" 
      ] 
     }, 
     "last name" : { 
      "$cond" : [ 
       { 
        "$eq" : [ 
         "last name", 
         "$FieldValues.FieldID" 
        ] 
       }, 
       "$FieldValues.FieldValue", 
       " skip" 
      ] 
     } 
    } 
}; 

group = { "$group" : { 
     "_id" : "$_id", 
     "first name" : { 
      "$max" : "$first name" 
     }, 
     "last name" : { 
      "$max" : "$last name" 
     } 
    } 
}; 

db.project.aggregate(unwind, match, proj, group) 
{ 
    "result" : [ 
     { 
      "_id" : ObjectId("511ff0a8521e66d41b0d35d7"), 
      "first name" : "sarah", 
      "last name" : "smith" 
     }, 
     { 
      "_id" : ObjectId("511ff0a8521e66d41b0d35d6"), 
      "first name" : "John", 
      "last name" : "smith" 
     } 
    ], 
    "ok" : 1 
} 
+0

我寫了一個在我的博客上創建這個管道的一般程序化方式:http://www.kamsky.org/1/post/2013/04/using-aggregation-framework-到重塑 - schema.html – 2013-04-22 03:07:50