◆ 昔のメモの発掘
◆ Node.js だと MongoDB のほうが楽かも?
◆ 結果が自動更新される部分はうまく使えば便利そう

Node.js で SQLite を使っていて そういえば前に RDB じゃない DB 使ってみたっけ と思いだして探してみるとでてきたメモ
タイムスタンプによると 2016 年の冬のようです
もうそこそこ古い情報になりつつありますね

今だとまた全然違うことになってるかもしれませんし これから使う人の参考にはなりませんが 今後自分が使う時に「前こんな感じだった気がするけど」みたいに思うことはあるので完全自分用メモとして貼り付けときます
ネットで見れるのは便利ですからね
ローカルのどこかだと探すのも大変ですから

ちなみに今 realm を調べてみると platform とかできてて有料とか書いててびっくりしました
https://realm.io/
データベースだけだとオープンソースで無料のままみたいです
https://realm.io/docs/
前は単純に DB だけって印象だったのですが いろいろ進化したのでしょうか
それか前面に押し出されてなかったから気づかなかっただけなのかもです



基本
var Realm = require("realm")

var test_schema = {
name: "test",
primaryKey: "id",
properties: {
id: "int",
text: "string",
}
}

var db = new Realm({path: "realm.db", schema: [test_schema]})

// 書き込む
db.write(() => {
db.create("test", {id: 1, text: "abcd"})
})

// 検索
db.objectForPrimaryKey("test", 1)
// RealmObject { id: 1, text: 'abcd' }

スキーマ定義が必要
Realm の引数で設定

> var Realm = require("realm")
> var test_schema = {
... name: "test",
... primaryKey: "id",
... properties: {
..... id: "int",
..... text: "string",
..... }
... }
> var db = new Realm({path: "realm.db", schema: [test_schema]})

schema プロパティで登録したスキーマが見える

> db.schema
[ { name: 'test',
properties: { id: [Object], text: [Object] },
primaryKey: 'id' } ]

開いてるdbを再度別スキーマを定義して開いても

> var test_schema2 = {
... name: "test2",
... properties: {
..... num: "int",
..... }
... }
> var db2 = new Realm({path: "realm.db", schema: [test_schema2]})
> db2.schema
[ { name: 'test',
properties: { id: [Object], text: [Object] },
primaryKey: 'id' } ]

変わってない

schema 指定無しでも一緒

> var db3 = new Realm({path: "realm.db"})
> db3.schema
[ { name: 'test',
properties: { id: [Object], text: [Object] },
primaryKey: 'id' } ]

クローズすれば更新できる

> db.close()
> db2.schema
[ { name: 'test',
properties: { id: [Object], text: [Object] },
primaryKey: 'id' } ]
> var db2 = new Realm({path: "realm.db", schema: [test_schema2]})
> db2.schema
[ { name: 'test2', properties: { num: [Object] } } ]

var Realm = require("realm")
var test_schema = {
name: "test",
primaryKey: "id",
properties: {
id: "int",
text: "string",
}
}
var test_schema2 = {
name: "test2",
properties: {
num: "int",
}
}

var db = new Realm({path: "realm01.db", schema: [test_schema]})
console.log(db.schema)
db.close()

var db2 = new Realm({path: "realm01.db", schema: [test_schema2]})
console.log(db2.schema)
db2.close()

var db3 = new Realm({path: "realm01.db"})
console.log(db3.schema)
db3.close()
[ { name: 'test',
properties: { id: [Object], text: [Object] },
primaryKey: 'id' } ]
[ { name: 'test2', properties: { num: [Object] } } ]
[ { name: 'test',
properties: { id: [Object], text: [Object] },
primaryKey: 'id' },
{ name: 'test2', properties: { num: [Object] } } ]

schema は追加や指定のものだけに制限したいとき
指定無しで開くと全部

var Realm = require("realm")
var test_schema = {
name: "test",
primaryKey: "id",
properties: {
id: "int",
text: "string",
}
}
var test_schema2 = {
name: "test2",
properties: {
num: "int",
}
}

// 2 つ作る
var db = new Realm({path: "realm01.db", schema: [test_schema, test_schema2]})
db.close()

// 2 のほうを指定
var db2 = new Realm({path: "realm01.db", schema: [test_schema2]})

// test は 1 のほう
db.write(_ => db.create("test", {id: 100, text: "a"}))
Error: Object type 'test' not found in schema.

すでに同名のスキーマがあると

> var db = new Realm({path: "realm01.db"})
> db.schema
[ { name: 'schema00',
properties:
{ id: [Object],
val: [Object],
val2: [Object],
obj: [Object],
list: [Object] },
primaryKey: 'id' },
{ name: 'schema01', properties: { x: [Object], y: [Object] } },
{ name: 'test',
properties: { id: [Object], text: [Object] },
primaryKey: 'id' },
{ name: 'test2', properties: { num: [Object] } } ]
> db.close()
> var test = {name: "test", properties: {x: "int", y: "int"}}
> var db = new Realm({path: "realm01.db", schema: [test]})
Error: Migration is required due to the following errors:
- Property 'test.y' has been added.
- Property 'test.x' has been added.
- Primary Key for class 'test has been removed.
- Property 'test.text' has been removed.
- Property 'test.id' has been removed.

close 後でも schema みれるが
DBにアクセスする場合は segmentation fault (write や objects など)

> var db = new Realm({path: "realm01.db", schema: [test_schema]})
> db.close()
> db.schema
[ { name: 'test',
properties: { id: [Object], text: [Object] },
primaryKey: 'id' } ]
> db.write(_ => db.create("test", {id: 11}))

segmentation fault

> var db = new Realm({path: "realm01.db", schema: [test_schema]})
> db.close()
> db.objects("test")

segmentation fault



doc にないのもメソッドも
(copy~, clear~)

> Realm.


Realm.Collection Realm.List Realm.Object
Realm.Results Realm.Types Realm.clearTestState
Realm.copyBundledRealmFiles Realm.defaultPath Realm.prototype
Realm.schemaVersion

> Realm.Collection
[Function: Collection]
> Realm.List
[Function: List]
> Realm.Object
[Function: RealmObject]
> Realm.Results
[Function: Results]
> Realm.Types
`Realm.Types` is deprecated! Please specify the type name as lowercase string instead!
{ BOOL: 'bool',
INT: 'int',
FLOAT: 'float',
DOUBLE: 'double',
STRING: 'string',
DATE: 'date',
DATA: 'data',
OBJECT: 'object',
LIST: 'list' }
> Realm.clearTestState
[Function: clearTestState]
> Realm.copyBundledRealmFiles
[Function: copyBundledRealmFiles]
> Realm.defaultPath
'./default.realm'
> Realm.schemaVersion
[Function: schemaVersion]

db プロパティ

> db.


db.addListener db.close db.create
db.delete db.deleteAll db.objectForPrimaryKey
db.objects db.removeAllListeners db.removeListener
db.write

db.path db.readOnly db.schema
db.schemaVersion



書き込み
→ create メソッド

トランザクションの外で create すると

> db.create("test", {id: 1, text: "abcd"})
Error: Can only create objects within a transaction.

書き込みはトランザクション内だけ
cbに引数はなし

> db.write(() => {
... db.create("test", {id: 1, text: "abcd"})
... })



データ一覧

> var res = db.objects("test")
> res
Results {
'0': RealmObject { id: 1, text: 'abcd' },
'1': RealmObject { id: 2, text: 'bcde' },
'2': RealmObject { id: 3, text: 'cdef' },
'3': RealmObject { id: 4, text: 'defg' },
'4': RealmObject { id: 5, text: 'efgh' },
'5': RealmObject { id: 6, text: 'fghi' } }



検索(主キーからのみ)

> var realm_obj = db.objectForPrimaryKey("test", 1)
> realm_obj
RealmObject { id: 1, text: 'abcd' }



フィルタ

> db.objects("test")
Results {
'0': RealmObject { id: 1, text: 'aa' },
'1': RealmObject { id: 2, text: 'ab' },
'2': RealmObject { id: 3, text: 'abc' },
'3': RealmObject { id: 4, text: 'abd' },
'4': RealmObject { id: 5, text: 'dde' },
'5': RealmObject { id: 6, text: 'def' } }
>
> db.objects("test").filtered(`text BEGINSWITH "ab" && id < $0`, 4)
Results {
'0': RealmObject { id: 2, text: 'ab' },
'1': RealmObject { id: 3, text: 'abc' } }

部分サポート
NSPredicate



Delete ALL

> db.objects("test")
// Results { '0': RealmObject { id: 1, text: 'abcd' } }
> db.write(() => db.deleteAll())
> db.objects("test")
// Results {}

Delete

> db.write(() => {
... db.create("test", {id: 1, text: "a"})
... db.create("test", {id: 2, text: "b"})
... db.create("test", {id: 3, text: "c"})
... db.create("test", {id: 4, text: "d"})
... db.create("test", {id: 5, text: "e"})
... db.create("test", {id: 6, text: "f"})
... })

> db.objects("test")
> var ro = db.objectForPrimaryKey("test", 1)
> ro
RealmObject { id: 1, text: 'a' }
> db.write(() => db.delete(ro))
> db.objects("test")
Results {
'0': RealmObject { id: 6, text: 'f' },
'1': RealmObject { id: 2, text: 'b' },
'2': RealmObject { id: 3, text: 'c' },
'3': RealmObject { id: 4, text: 'd' },
'4': RealmObject { id: 5, text: 'e' } }
>
> var ro3 = db.objectForPrimaryKey("test", 3)
> var ro4 = db.objectForPrimaryKey("test", 4)
> db.write(() => db.delete([ro3, ro4]))
> db.objects("test")
Results {
'0': RealmObject { id: 6, text: 'f' },
'1': RealmObject { id: 2, text: 'b' },
'2': RealmObject { id: 5, text: 'e' } }
>
> db.objects("test").filtered("id == $0 || id == $1", 2, 4)
Results { '0': RealmObject { id: 2, text: 'b' } }
> db.objects("test").filtered("id == $0 || id == $1", 2, 6)
Results {
'0': RealmObject { id: 6, text: 'f' },
'1': RealmObject { id: 2, text: 'b' } }
> var res = db.objects("test").filtered("id == $0 || id == $1", 2, 6)
> res
Results {
'0': RealmObject { id: 6, text: 'f' },
'1': RealmObject { id: 2, text: 'b' } }
> db.write(() => db.delete(res))
> db.objects("test")
Results { '0': RealmObject { id: 5, text: 'e' } }

消すオブジェクトを指定するので
どのスキーマからというのは無し

deleteAll は全部消える
スキーマ単位は自分で objects("schema-name") を delete に渡す



トランザクションメソッドは同期的

> db.write(() => {
... console.log(1)
... db.create("test", {id: 3, text: "www"})
... }), console.log(2)
1
2



結果は [live] collections
追加後に result を見ると

> db.write(() => {
... db.create("test", {id: 2, text: "xyz"})
... })
> res
Results {
'0': RealmObject { id: 1, text: 'abcd' },
'1': RealmObject { id: 2, text: 'xyz' } }

結果はアクティブ HTMLElements みたいな



RealmObject の方も

var db = new Realm({path: "realm01.db", schema: [test_schema]})
var realm_obj = db.objectForPrimaryKey("test", 1)
console.log(realm_obj)
// RealmObject { id: 1, text: 'abcd' }

db.write(() => {
db.create("test", {id: 1, text: "changed"}, true)
})

console.log(realm_obj)
// RealmObject { id: 1, text: 'changed' }

db.close()
console.log(realm_obj)
Error: Accessing object of type test which has been deleted

更新に応じて変わる
その特性上 close 後には結果を代入した変数にアクセスできなくなる

delete も同じエラー

> var ro = db.objectForPrimaryKey("test", 1)
> db.write(() => db.delete(ro))
> ro
Error: Accessing object of type test which has been deleted

Results や RealmObject の isValid でアクセス可能か見れる

> var res = db.objects("test")
> var ro = db.objectForPrimaryKey("test", 1)
> res
Results { '0': RealmObject { id: 1, text: 'aa' } }
> ro
RealmObject { id: 1, text: 'aa' }
> res.isValid()
true
> ro.isValid()
true
> db.write(() => db.deleteAll())
> res.isValid()
true
> ro.isValid()
false
> db.close()
res.isValid()
false

オブジェクトは消された時 DBが閉じた時
結果のセットは消えないので DB閉じたときだけ not valid



Realm.Results, Realm.List は Realm.Collection を継承してる

> result
Results { '0': RealmObject { id: 1, text: 'changed' } }
> result.__proto__.constructor
[Function: Results]
> result.__proto__.__proto__.constructor
[Function: Collection]
> result.__proto__.__proto__.__proto__.constructor
[Function: Observable]
> result.__proto__.__proto__.__proto__.__proto__.constructor
[Function: Object]



snapshot

> var res = db.objects("test")
> res
Results { '0': RealmObject { id: 1, text: 'abcd' } }
> var snapshot = res.snapshot()
> snapshot
Results { '0': RealmObject { id: 1, text: 'abcd' } }

同じ RealmObject
変化させると

> db.write(() => db.create("test", {id: 2, text: "xyz"}))
> res
Results {
'0': RealmObject { id: 1, text: 'abcd' },
'1': RealmObject { id: 2, text: 'xyz' } }
> snapshot
Results { '0': RealmObject { id: 1, text: 'abcd' } }

snapshot は変化しない
でもDB閉じたら

> db.close()
> res
Results {}
> snapshot
Results {}

消える

RealmObject 削除の場合

> var res = db.objects("test")
> res
Results {
'0': RealmObject { id: 1, text: 'abcd' },
'1': RealmObject { id: 2, text: 'xyz' } }
> var snapshot = res.snapshot()
> snapshot
Results {
'0': RealmObject { id: 1, text: 'abcd' },
'1': RealmObject { id: 2, text: 'xyz' } }
> db.write(() => db.deleteAll())
> snapshot
Results { '0': null, '1': null }

snapshot でも消えるけど値が null になって キーは残ってる



Results に addListener

> var coll = db.objects("test")
> coll
Results { '0': RealmObject { id: 1, text: 'abcd' } }
> coll.addListener(function(...args){console.log(args)})
> db.write(() => {
... db.create("test", {id: 5, text: "55"})
... db.create("test", {id: 6, text: "666"})
... })
> [ Results {
'0': RealmObject { id: 1, text: 'abcd' },
'1': RealmObject { id: 5, text: '55' },
'2': RealmObject { id: 6, text: '666' } },
{ deletions: [], insertions: [ 1, 2 ], modifications: [] } ]

コールバックの引数は collection と changes
changes には collection の index が入ってる
主キーじゃない





var schema_obj00 = {
name: "schema00",
primaryKey: "id",
properties: {
id: {
type: "int",
},
val: {
type: "int",
default: 100,
indexed: true,
},
val2: {
type: "string",
optional: true,
},
obj: {
type: "schema01",
},
list: {
type: "list",
objectType: "schema01",
}
}
}
var schema_obj01 = {
name: "schema01",
properties: {
x: "double",
y: "double",
}
}

var db = new Realm({path: "realm01.db", schema: [schema_obj00, schema_obj01]})

db.write(() => {
db.create("schema00", {
id: 1,
obj: {x: 1.23, y: 4.56},
list: [{x: -1, y: -2}, {x:100, y: 200}],
})
})
db.objects("schema00")
// Results {
// '0':
// RealmObject {
// id: 1,
// val: 100,
// val2: null,
// obj: RealmObject { x: 1.23, y: 4.56 },
// list: List { '0': [Object], '1': [Object] } } }
> db.objects("schema01")
// Results {
// '0': RealmObject { x: 1.23, y: 4.56 },
// '1': RealmObject { x: -1, y: -2 },
// '2': RealmObject { x: 100, y: 200 } }