LoginSignup
5
6

More than 5 years have passed since last update.

Opa はオブジェクトをどのように MongoDB に格納するのか?

Last updated at Posted at 2014-06-17

環境

  • Opa compiler (c) MLstate -- version 1.1.1 -- build 4308
  • MongoDB v2.6.0

方法

簡単なコードを書いてDBにデータを格納し、mongo クライアントから
結果を確認する。

simple

type x =
  {
    int foo,
    string bar,
    float baz,
    bool hoge,
    void fuga
  }

database dbtest {
  x /xs[{foo}]
  /xs[_]/hoge = { false }
}

/dbtest/xs[{foo: 1}] <- {bar: "hello", baz: 3.14, hoge: true, fuga: {}}
> db.xs.find()
{
        "_id" : ObjectId("539f3e9d68a84ebe3504cd4e"),
        "foo" : NumberLong(1),
        "bar" : "hello",
        "hoge" : true,
        "baz" : 3.14
}
  • なんか bool のフィールドにはデフォルト値を設定しないとコンパイラに怒られた。
  • えっ、void は入らないの?
  • それ以外はフツー。

tuple

type x =
  {
    int foo,
    (string, int) bar
  }

database dbtest {
  x /xs[{foo}]
}

/dbtest/xs[{foo: 1}] <- {bar: ("hello", 3)}
> db.xs.find()
{
        "_id" : ObjectId("539f3e9d68a84ebe3504cd4e"),
        "foo" : NumberLong(1),
        "bar" : {
                "f2" : NumberLong(3),
                "f1" : "hello"
        }
}
  • タプルは自動的に "f1", "f2", ... というプロパティが作られて入る。

variant

type s = {Foo} or {int Bar} or {string Xyz} or {(int, string) Blah}
type x = {
  s foo,
  s bar
}

database dbtest {
  x /xs[{foo}]
}


/dbtest/xs[{foo: {Foo}}] <- {bar: {Bar: 1}}
/dbtest/xs[{foo: {Xyz: "aaa"}}] <- {bar: {Blah: (3, "hoge")}}

> db.xs.find()
{
        "_id" : ObjectId("539f524468a84ebe3504cd53"),
        "foo" : {
                "Foo" : null
        },
        "bar" : {
                "Bar" : NumberLong(1)
        }
}
{
        "_id" : ObjectId("539f524468a84ebe3504cd54"),
        "foo" : {
                "Xyz" : "aaa"
        },
        "bar" : {
                "Blah" : {
                        "f2" : "hoge",
                        "f1" : NumberLong(3)
                }
        }
}
  • コンストラクタ名がオブジェクトのプロパティ名となる。
  • https://github.com/MLstate/opalang/wiki/The-type-system に "type color = { Red } or { Green } or { Blue } defines color as a sum with three cases, each of them implicitly of type void." と書かれているので、"Foo" : null は納得。

option

type x = {
  int foo,
  option(int) bar
}


database dbtest {
  x /xs[{foo}]

}

/dbtest/xs[{foo: 1}] <- {bar: {some: 1} }
/dbtest/xs[{foo: 2}] <- {bar: {none} }

> db.xs.find()
{
        "_id" : ObjectId("53a04f9568a84ebe3504cd67"),
        "foo" : NumberLong(1),
        "bar" : {
                "some" : NumberLong(1)
        }
}
{
        "_id" : ObjectId("53a04f9568a84ebe3504cd68"),
        "foo" : NumberLong(2),
        "bar" : {
                "none" : null
        }
}
  • option も variant として定義されてるだけなので、当然の結果ですねー。

foreign

type t = {
  string foo,
  int bar
}

type x = {
  t first,
  t second,
  int third
}

database dbtest {
  t /ts[{foo}]
  x /xs[{first, second}]
}

s1 = {foo: "hello", bar: 100}
s2 = {foo: "world", bar: 200}
/dbtest/ts[{foo: "hello"}] <- s1
/dbtest/ts[{foo: "world"}] <- s2
/dbtest/xs[{first: s1, second: s2}] <- {third: 111}

> db.ts.find()
{
        "_id" : ObjectId("539f563168a84ebe3504cd57"),
        "foo" : "hello",
        "bar" : NumberLong(100)
}
{
        "_id" : ObjectId("539f563168a84ebe3504cd58"),
        "foo" : "world",
        "bar" : NumberLong(200)
}

> db.xs.find()
{
        "_id" : ObjectId("539f563168a84ebe3504cd59"),
        "first" : {
                "foo" : "hello",
                "bar" : NumberLong(100)
        },
        "second" : {
                "foo" : "world",
                "bar" : NumberLong(200)
        },
        "third" : NumberLong(111)
}
  • _id で参照する形にはならず、first にも second にも展開されたオブジェクトがそのまま入ってます。

list

type x = {
  int foo,
  list(int) bar
}


database dbtest {
  x /xs[{foo}]
}

/dbtest/xs[{foo: 1}] <- {bar: [1]}
/dbtest/xs[{foo: 2}] <- {bar: [1, 2, 3]}
/dbtest/xs[{foo: 3}] <- {bar: []}
> db.xs.find()
{
        "_id" : ObjectId("53a046dd68a84ebe3504cd5e"),
        "foo" : NumberLong(1),
        "bar" : [
                NumberLong(1)
        ]
}
{
        "_id" : ObjectId("53a046dd68a84ebe3504cd5f"),
        "foo" : NumberLong(2),
        "bar" : [
                NumberLong(3),
                NumberLong(2),
                NumberLong(1)
        ]
}
{
        "_id" : ObjectId("53a046dd68a84ebe3504cd60"),
        "foo" : NumberLong(3),
        "bar" : [ ]
}
  • list は配列として入る。
  • [1, 2, 3] が NumberLong(3), NumberLong(2), NumberLong(1) の順序で入っているがなんだこれは?
  • 空は空配列として入る。

map

type x = {
  int foo,
  map(string, float) bar
}


database dbtest {
  x /xs[{foo}]
}

/dbtest/xs[{foo: 1}] <- {bar: Map.From.assoc_list([("pi", 3.14), ("e", 2.72)])}

> db.xs.find()
{
        "_id" : ObjectId("53a049e068a84ebe3504cd62"),
        "foo" : NumberLong(1),
        "bar" : {
                ""pi"" : 3.14,
                ""e"" : 2.72
        }
}
  • map は object として入る。が、キーが文字列のときは二重にクォートされるんだな。

set

type x = {
  int foo,
  intset bar
}


database dbtest {
  x /xs[{foo}]

}

/dbtest/xs[{foo: 1}] <- {bar: Set.From.list([1, 3, 1, 5])}

> db.xs.find()
{
        "_id" : ObjectId("53a0538968a84ebe3504cd6e"),
        "foo" : NumberLong(1),
        "bar" : {
                "5" : null,
                "3" : null,
                "1" : null
        }
}
  • set は value が null の map なのだな。

xhtml

type x = {
  int foo,
  xhtml bar
}

database dbtest {
  x /xs[{foo}]
}


/dbtest/xs[{foo: 1}] <- {bar: <p>Hello</p>}

$ make run
### Building executable dbtest.exe 
opa --opx-dir _build --import-package stdlib.database.mongo    --conf opa.conf --conf-opa-files  -o dbtest.exe --build-dir _build/dbtest.exe
Error: File "src/model.opa", line 7, characters 1-34, (7:1-9:1 | 39-72)
Elements of type Dom.event -> void cannot be stored in the database
make: *** [dbtest.exe] Error 1
  • ほほーぅ。xhtml 型は DB には入れられない。というか、function 型がダメ?

function

type x = {
  int foo,
  (int -> int) bar
}


database dbtest {
  x /xs[{foo}]

}

/dbtest/xs[{foo: 1}] <- {bar: function (x) { x * 2 } }

$ make run
### Building executable dbtest.exe 
opa --opx-dir _build --import-package stdlib.database.mongo    --conf opa.conf --conf-opa-files  -o dbtest.exe --build-dir _build/dbtest.exe
Error: File "src/model.opa", line 7, characters 1-35, (7:1-10:1 | 46-80)
Elements of type int -> int cannot be stored in the database
make: *** [dbtest.exe] Error 1
  • やはり関数はダメ、と。

以上、だいたいこんなもんですかね。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6