在reduce之前,MongoDB组多次映射两次

时间:2011-03-17 22:30:11

标签: c# linq mongodb map mapreduce

我有一系列事件= [timestamp,accountId,deviceId,rfid ...]

-rfids可以为空,但其他所有内容都不可为空 -rfid通过deviceId报告

我需要找到系统中每个rfid的状态。乍一看,如果我们映射{accountId,deviceId,rfid},这似乎微不足道。但是,rfids状态也依赖于报告deviceIds事件。当设备报告时,它将rfid值设置为null(例如,设备可能会重启)。如何基于{accountId,deviceId,rfid}定义单个映射函数,然后将映射集合与所有{accountId,deviceId,null}映射集合联合起来?

现在我使用linq如下获取我想要的数据集:

events.GroupBy(new{deviceId, accountId}).Select( x=>new{
  Key= x.Key
  Value = x.GroupBy(y=>new{y.accountId, y.rfid}).Union(x.Where(z=>z.rfid== null))).ToList()
});

2 个答案:

答案 0 :(得分:1)

必须在数据集上进行两次map / reduce传递 1)map {acctid,deviceId,rfid} =>减少到数组[事件] 2)映射(1){acctId,deviceId} =>的结果根据statusCode

减少到锁存的rfids数组

这里需要记住的一件事是,emit函数值参数(第二个参数)应该与结果集具有相同的结构。这是因为迭代执行减少!!在生成初始事件数组时,这是一个痛点。

答案 1 :(得分:0)

好吧,不确定这是不是“从森林中看不到树”的那种问题。如果按{deviceId, accountId}分组,则组中已有null和非null rfids。如果我理解你正确{deviceId,accountId}有一个唯一的rfid,如果是这样,只需从组中提取第一个非null rfid及其所有元素作为值:

var p = from e in events 
    group e by new { e.accountId, e.deviceId } into g
    let rfid = g.First(ge => ge.rfid != null).rfid
    select new { 
        Key = new { g.Key.accountId, g.Key.deviceId, rfid }, 
        Values = g.ToList() 
    };

如果另一方面你的设备,帐户组合可以有多个rfids然后你没有一个合理的解决方案,因为一个无效的rfid可能属于任何帐户,设备,rfid组合。

注意:要使其正常工作,每个组合中必须至少有一个非null rfid,否则First()将崩溃并刻录。然后,如果你在combe中没有非null的rfid,那么首先无法知道它是什么,一个选项是使用FirstOrDefault,但是你会得到多个空键,每个帐户一个,设备没有rfid的组合。