Contextureにおけるgroupby
(下書きです。)
Contextureはfunctional database modelをベースとしたDBMSです。
Dataflowもしくはfunctional reactive programmingな仕組みを取り入れています。
functional database modelは、永続化された辞書や連想配列などのデータ構造を
関数と見なして操作するデータベースモデルです。
関数なので、KVSと同じように、キーをつっこめば値が得られる、というのが一番基本的なクエリーになります。
関数なので、複数の関数の合成、つまり直列につなぐ事や並列につなぐことができます。
関数の合成や操作は、HaskellのArrowと雰囲気は同じです。
http://d.hatena.ne.jp/r-west/20070720/1184946510
Arrowでは直列につなぐ演算子は「>>>」ですが、
Contextureではただの「.」(ドット)を使います。
Contextureでは多値を返す関数を基本として、合成操作もすこし拡張してありますが、
その説明はまた今度。
社員や、部署の関係をあらわすデータを例にとります。
所属 :: 社員ID -> 部署ID
所属 = {1:[101],2:[101], 3:[102], 4:[101]}
社員名 :: 社員ID -> String
社員名 = {1:["田中"], 2:["鈴木"], 3:["山田"], 4:["後藤"]}
部署名 :: 部署ID -> String
部署名 = {101:["開発部"], 102:["人事部"]}
年齢 :: 社員ID -> Integer
年齢 = {1:[30], 2:[30],3:[30], 4:[40]}
[1] => 所属.部署名 => ["開発部"]
[1, 3] => 所属.部署名 => ["開発部", "人事部"]
[1] => (所属.部署名,社員名) => [("開発部", "田中")]
~は、inverseの単項演算子です。
~所属は、所属のinverseで、
所属 :: 社員ID -> 部署ID
所属 = {1:[101],2:[101], 3:[102], 4:[101]}
なので、
~所属 :: 社員ID -> 部署ID
~所属 = {101:[1,2,4],102:[3],}
になります。
[101] => (部署名, ~所属.(社員名,年齢))
=> [
("開発部", [
("田中", 30), ("鈴木", 30), ("後藤", 40)]),
("開発部", [
("山田", 30)])]
今回はContextureにおけるgroupbyについていまのところ考えている仕様を説明します。
groupbyは、ある属性でまとめるような操作になります。
groupby(~所属, 年齢)
は、~所属を 年齢でグルーピングする感じです。
型は
groupby(~所属, 年齢) :: 部署ID -> Integer -> 社員ID
になります。つまり、部署IDが決まって、Integer(年齢)がきまって
初めて社員IDが得られる、引数を二つとる関数のようなものになります。
データ構造としては、辞書の入れ子になります。
カリー化された関数のようなかんじです。
データは、
groupby(~所属, 年齢) = {
101:{
30:[1, 2],
40:[4]},
102:{
30:[3]}}
のようになります。
例としては、つぎのようなかんじになります。
[101] => groupby(~所属, 年齢)
=> [{
30:[1, 2],
40:[4]}]
[101] => groupby(~所属, 年齢).社員名
=> [{
30:["田中", "鈴木"],
40:["後藤"]}]