グループ化と適用
このトピックの例では、LINQ の "グループ化" 機能を使用して、イベントをイベント グループに分割する方法を示します。集計やその他の操作をイベント グループに対して実行することによって、各グループの計算を別々に行うことができます。各グループに適用される操作のセットは、適用分岐と呼ばれます。適用分岐は、1 つの "グループ化と適用" ステートメント内で暗黙的に使用できます。また、複雑なサブクエリが含まれる場合は、独立した LINQ ステートメントとして使用することもできます。適用分岐は、グループおよび適用構造内で終了することに注意してください。たとえば、グループ化の外からグループ化されたストリームを他のストリームに結合することはできません。
使用例
次の例では、指定された modulo 関数を使用して、イベントをグループ化します。次に、スナップショット ウィンドウを各グループに適用して、各グループのペイロード列における平均を個別に計算します。そのため、適用分岐はウィンドウと集計で構成されます。
// Assuming the following input event type for inputStream:
public class MyPayload
{
public int i;
public float j;
}
var avgCount = from v in inputStream
group v by v.i % 4 into eachGroup
from window in eachGroup.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
select new { avgNumber = window.Avg(e => e.j) };
前の例では、単一のペイロード フィールドを含むストリームが生成されました。このフィールドには、グループごとの各スナップショット ウィンドウ内にある j フィールドの平均が格納されます。
次の例のように、"group by" 句で元の型の投影をグループ化することもできます。
var result = from e in source.AlterEventDuration(e => TimeSpan.FromMinutes(10))
group new { myVal = e.Value * 10 } by e.SourceId into g
from win in g.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
select new
{
avg = win.Avg(e => e.myVal)
};
通常、集計結果を各グループに関連付けることができるように、グループ化キーは保持する必要があります。次の例では、グループ化キーを取得する方法を示します。
var avgCount = from v in inputStream
group v by v.i % 4 into eachGroup
from window in eachGroup.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
select new { avgNumber = window.Avg(e => e.number), groupId = eachGroup.Key };
複数のキーに基づいたグループ化が可能であり、入力ストリームにおける一意のキーの組み合わせはそれぞれ、個別のグループになります。この場合、グループ化キーは、最終的な射影で明示的に取得できるように匿名の型定義に含める必要があります。すべてのグループ化フィールドを参照する必要があることに注意してください。次の例では、2 つのイベントのペイロード フィールドを使用してイベントをグループ化し、新しいキー名をイベントの 1 つに割り当てます。
// Assuming the following input event type for inputStream:
public class MyPayload
{
public int section;
public string category;
public float value;
}
var avgCount = from v in inputStream
group v by new { sec = v.section, v.category } into eachGroup
from window in eachGroup.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
select new { avgNumber = window.Avg(e => e.value), section = eachGroup.Key.sec, category = eachGroup.Key.category };
次の例に示すように、一連の操作を含む適用分岐はより複雑になる可能性があります。
// Assuming the following input event type for inputStream:
public class MyPayload
{
public int section;
public string category;
public float value;
}
var result = from s in source
group s by s.section into sg
from e in
(from e in sg
group e by e.category into cg
from win in cg.TumblingWindow(TimeSpan.FromMinutes(5), HoppingWindowOutputPolicy.ClipToWindowEnd)
select new { cat = cg.Key, top = win.Max(e => e.value) })
select new { sec = sg.Key, e.cat, e.top };
次の例は、メーターの電力測定値のストリームを想定しています。ここでは、複数のメーターのデータが含まれます。この例では、各読み取り値に、同じメーターの最後の 10 分の平均値の注釈が付けられています。まず、クエリはメーター ID ごとに受信データをグループ化します。各グループで、10 分間の平均値が計算され、元のメーター イベントに結合されます。
// Assuming the following input event type for sensorStream:
public class MeterReading
{
public string meterId;
public float usage;
}
var resultB = from s in sensorStream
group s by s.meterId into g
from e in
(from left in g
from right in
(from win in g
.AlterEventDuration(e => TimeSpan.FromMinutes(10))
.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
select new { avg = win.Avg(e => e.usage) })
select new { right.avg, left.usage })
select new { slidingAvg = e.avg, e.usage, g.Key };
上記で示したように、適用分岐を表す関数は applyIn 以外の受信ストリームに統合することはできません。