2015-07-20 43 views
1

我工作的一個流星應用程序,我有數據格式的每週時間表 -MongoDB的分組查詢

events: 
    event: 
     day: "Monday" 
     time: "9am" 
     location: "A" 
    event: 
     day: "Monday" 
     time: "10am" 
     location: "B" 

有每天大量的條目。我可以運行一個查詢,將返回格式的對象 -

day: "Monday" 
    events: 
     event: 
     time: "9am" 
     location: "A" 
     event: 
     time: "10am" 
     location: "B" 

我可以存儲在第二格式的對象,但傾向於第一種便於刪除和更新個別事件。

如果有一個很好的方法來做到這一點,我還希望按星期幾排序。

+0

,你能否告訴我們,表示上述數據準確MongoDB的文檔架構在週一的事件來遍歷? – chridam

+0

'事件= { \t 「_id」:INT, \t 「天」:字符串, \t 「時間」:字符串, \t 「位置」:字符串 }' – kinsey

+0

我將有一個表單添加新的事件,刪除或修改,但是當我顯示它們時,它們將按日分組。我知道我可以在前端做到這一切,但在查詢中可能會更整潔。第一次這樣做可能會導致所有錯誤。 – kinsey

回答

0

有幾個選項:

  1. 您可以使用聚合的命令,但被警告,你將失去反應:這意味着,除非你重新加載模板,您將無法獲得外部更新。您還需要使用a package to add the aggregation command to Meteor才能實現。

  2. 我個人最喜歡的:你不需要聚合(和鬆散的反應)來實現你的數據轉換。您可以使用簡單的Collection.find()查詢並使用cursor.Observe()和條件修改的巧妙組合對其進行擴展/減少/修改。看看這個答案,它爲我做了訣竅(我需要一些黑色列表的一些字段,但你可以很容易地適應你的組/分揀案例):https://stackoverflow.com/a/30813050/3793161。如果您需要更多詳細信息,請留言

  3. 如果您計劃擁有多臺服務器,請注意每臺服務器都必須遵守,以免導致不必要的負載。所以我的第三個解決方案是使用集合鉤子或方法來更新每個日期/用戶的每個事件的更多字段(無論您需要什麼)。請參閱@David Weldon關於此處的回答:https://stackoverflow.com/a/31190896/3793161。在你的情況下,這可能意味着重新考慮你的數據庫結構以適應你的需求(即增加更多的字段,以便你可以在insert上更新它們。

編輯這裏有您的評論的一些想法:

如果你堅持你的問題說明了什麼,則需要7個文件,每天一個,有events場,其中你把所有的事件。如果您在發送之前需要重新設計收集結構,我的第二個解決方案很好。然而,就你而言,你只需要一個對象week與7個子對象匹配的星期幾。

我勸你還是可能的方法:

  • 使用聚合的方法,例如用@chridam描述。被警告,你將無法直接得到有序數組,如蒙戈$group文件指出

$組不責令其輸出文檔

所以,你需要對它們進行排序(通過使用,例如_.sortBy()通過每一天內每小時),然後回到你的方法的結果。順便說一句,如果你想知道什麼是你的方法調用,客戶方回事,這裏是你應該怎麼寫電話:

Meteor.call("getGroupedDailyEvents", userId, function(error, result){ 
    if(error){ 
     console.log("error", error); 
    } 
    if(result){ 
     //do whatever you need 
    } 
}); 
  • 使數據排序客戶方。您正在尋找一種矯枉過正的解決方案,因爲afaik不需要過濾任何數據以將其與用戶保持關聯,並且無論如何您都將發送數據(僅使用其他結構)。這是這樣更容易使一個簡單的助手在你的模板:

    Template.displaySchedule.helpers({ 
    
        "monday_events": function() { 
         return _.sortBy (events.find({day:"Monday"}).fetch(), "time") 
        }, 
        //add other days 
    ); 
    

它假定您time字段的格式是排序這種方式。如果沒有,你只需要創建一個函數來根據它們的格式對它們進行排序,或者將原始格式更改爲更適合的格式。

其餘(HTML),也只是使用{{#each monday_events}}

+0

在我的情況下,我不認爲失去反應性是一個問題,所以選擇1將工作,如果我能夠正確的。我也對選項2感興趣,但並不真正瞭解它。我將繼續通讀您的示例,並希望能夠對其適用於我的案例提供一個粗略指導。 3,它是一個小應用程序,不會在多臺服務器上運行。 – kinsey

+0

我更新了我的回答 – Billybobbonnet

+0

在這個例子中,你說的聚合方法太過分了。我想這樣做會簡化別處的代碼。由於它簡化的代碼並不是特別複雜,所以它絕對是頂級的。你的第二個選擇是做到這一點的方法。雖然我很好的學習練習,但我會首先得到聚合器的例子。這些日子實際上是以數字1-7存儲的,所以我可以進一步簡化它,方法是將「monday_events」替換爲更通用的東西,並傳入一個整數,爲每一天創建一個新行。 – kinsey

0

爲了實現期望的結果,使用aggregation framework其中$group管道運算符組中的所有輸入文檔並應用累加器表達$push基團來獲得的事件陣列。

你的管道應該是這樣的:

var Events = new Mongo.Collection('events'); 
var pipeline = [   
    { 
     "$group": { 
      "_id": "$day", 
      "events": { 
       "$push": { 
        "time": "$time" 
        "location": "$location" 
       } 
      } 
     } 
    }, 
    { 
     "$project": { 
      "_id": 0, "day": "$_id", "events": 1 
     } 
    } 
]; 
var result = Events.aggregate(pipeline); 
console.log(result) 

您可以添加meteorhacks:aggregate package實現流星聚集:

添加到您的應用

meteor add meteorhacks:aggregate 

由於這包曝光.aggregate m在Mongo.Collection實例中,您可以定義一個獲取聚合結果數組的方法。例如

if (Meteor.isServer) { 
    var Events = new Mongo.Collection('events'); 
    Meteor.methods({ 
     getGroupedDailyEvents: function() { 
      var pipeline = [   
       { 
        "$group": { 
         "_id": "$day", 
         "events": { 
          "$push": { 
           "time": "$time" 
           "location": "$location" 
          } 
         } 
        } 
       }, 
       { 
        "$project": { 
         "_id": 0, "day": "$_id", "events": 1 
        } 
       } 
      ]; 
      var result = Events.aggregate(pipeline); 
      return result; 
     } 
    }); 
} 

if (Meteor.isClient) { 
    Meteor.call('getGroupedDailyEvents', logResult); 

    function logResult(err, res) { 
     console.log("Result: ", res) 
    } 
} 
+0

這太棒了,謝謝!我可以按照你的例子,但是當我調用函數時,我沒有得到響應。 'Meteor.methods({ \t 'getTrainingList':函數(){ \t \t變種管道= [ \t \t { $組:{ _id: '$日', 訓練:{ $推:{ 時間: '$時間', 位置: '$位置' } } } }/*, { $項目:{ _id:0,天: '$ _id',培訓:1 } } */ \t]; \t var result = TrainingList.aggregate(pipeline); 返回結果; \t} });' – kinsey

+0

@kinsey你是如何調用函數的? – chridam

+0

抱歉忽略那些開啓/關閉評論標籤..該代碼包含在內 – kinsey