2015-07-20 42 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