开发者

MongoDB groupby multiple times map twice before reduce

开发者 https://www.devze.com 2023-02-17 08:01 出处:网络
I have a collection of events=[ timestamp, accountId, deviceId, rfid ...] -rfids is nullable, but everything else is not nullable

I have a collection of events=[ timestamp, accountId, deviceId, rfid ...]

-rfids is nullable, but everything else is not nullable -the rfid reports through a deviceId

I need to find the state of every rfid in my system. At first glance this seems trivial if we map on {accountId,deviceId,rfid} however, the rfids state is also dependent on the reporting deviceIds events. When the device reports, it sets the rfid value to null (for example the device may power cycle). How would I go about defining a single mapping function based on the {accountId,deviceId,rfid} and then unioning the map collection with all the {accountId,deviceId, null} mapped collection?

right now I use linq as follows to get my desired dataset:

events.GroupBy(new{deviceId, accountId}).Select( x=>new{
  K开发者_运维百科ey= x.Key
  Value = x.GroupBy(y=>new{y.accountId, y.rfid}).Union(x.Where(z=>z.rfid== null))).ToList()
});


Two map/reduce passes have to be made on the dataset 1)map {acctid,deviceId,rfid} => reduce to array[events] 2)map results of (1) {acctId,deviceId} => reduce to array of latched rfids based on statusCode

A key thing to remember here is that the emit functions value parameter (2nd parameter ) should have the same structure as the result set. This is because reduce is performed iteratively!! this was a pain point when generating the inital events array.


Well, not sure if this is the "can't see the tree from the forest" kind of problem. If you group by {deviceId, accountId} you already have both null and non-null rfids in the group. If I understood you right a {deviceId, accountId} has a unique rfid to it, if so, just extract the first non-null rfid from the group and all its elements as values:

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() 
    };

If on the other hand your device, account combo can have multiple rfids then you dont have a sound solution as a nulled rfid could belong to any account,device,rfid combo.

Note: for this to work you must have at least one non-null rfid in each combo, otherwise the First() will crash and burn. Then again, if you have no non-null rfid in combe there is no way to know what it is in the first place, one option is to use FirstOrDefault, but then you'll get multiple null keys, one for each account,device combo without rfid.

0

精彩评论

暂无评论...
验证码 换一张
取 消