前回の投稿から半年以上過ぎましたが、OrientDB の紹介3回目です
前の2回は以下の通りです
・オープンソース NoSQL データベース OrientDB を使ってみる #1
・オープンソース NoSQL データベース OrientDB を使ってみる #2
データ間の関連(リレーション)について紹介します
データ間の関連とは2つの異なるレコードを関連付けることで、データの透過的な参照や複雑なデータ構造の表現が可能となります
OrientDB では参照型( Referenced relationships )と組込型( Embedded relationships )という2種類の関連付けをサポートしています
参照型は、フィールドに対象レコードのレコードID(全レコードにてユニークとなるID)を持つことでデータ間の関連付けを行います
そのため、関連付ける各レコードは独立したレコードとして各々参照できる必要があります
対して組込型は、フィールドに直接レコードをそのものを設定するもので、組み込まれたレコードを独立して参照することはできません
また、参照、組込型として関連付けられるデータは 1:1 だけでなく、各々 List 、 Set 、 Map という 1:N 、または N:M の関係を作ることができます
(今回はこの部分の説明の詳細は省略させて頂きます)
それでは実際にデータの登録を行い、どのような構造のレコードが生成されるかを説明したいと思います
今回使用した環境は下記の通りです
・Mac OS X 10.6.7
・Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326)
・OrientDB 0.9.25
・NetBeans 7.0 RC2
以降は上記環境にて、サーバの起動、専用クライアント(コンソール)の接続まで完了している前提で進めます
サーバやクライアントの起動方法、クライアントを使用したレコード操作などについては、前々回のエントリを参照ください
また、文中で使われるレコードIDは環境により異なりますので、お使いの環境にあわせて読み替えてください
まず、テストデータを登録するため、下記クエリを実行して Person クラスと Group クラスを作成します
( ">" はプロンプトとなりますので、コピーして実行する際にはご注意ください)
次に参照型の関連フィールドを持つレコードを作成します
関連付けるレコードは先ほど登録した Group クラスのレコードです
下記クエリを実行して、 レコードを登録します
(そのため、事前に関連づけるレコードIDを知っておく必要があります)
上記の場合、 "group" というフィールドにレコードIDを設定しており、これで Person クラスと Group クラスの各レコードが関連付けられることとなります
下記コマンドで Person クラスに6レコード登録されたことが確認できます
以下は select 文にて group フィールドに関連付けられた、 Group クラスの name フィールドを参照しています
(where 句にある "@rid" はレコードIDを意味するレコード属性になります)
(import 文、パッケージ名は省略しますのでご注意下さい)
参照型の関連付けを行う方法はクエリを使用したケースと同様にフィールドにレコードIDを設定します
Java API にてレコードID( Java API では ORID クラスにて表現されています)を取得するには、ODocument クラスの getIdentity() メソッドを使用します
なお、新規レコードの場合、事前に save() メソッドを呼び出してデータベースに登録が完了していないとレコードIDは取得できませんので、ご注意ください
レコードを取得する場合は下記のようになります
次に組込型の関連付けですが、現在(2011年4月12日時点)のバージョンではクエリによる組込型のレコードの登録、更新(参照は可能です)は対応しておらず、 Java API でのみとなります
Java API を利用する場合の登録は以下のようになります
参照型と大きく異なる点は作成した Weapon クラスの save()メソッドを呼び出していない点、取得した Person クラスの "weapon" フィールドに設定する際、第3引数に "OType.EMBEDDED" を設定している点です
レコードの参照方法に関しては、組込型も参照型も差異はありません
組込まれたレコードのフィールドも同様の形式で参照可能です
次回は、 OrientDB のグラフデータベースとしての機能を紹介したいと思います
(次はあまり期間をあけないようしたいと思います…)
前の2回は以下の通りです
・オープンソース NoSQL データベース OrientDB を使ってみる #1
・オープンソース NoSQL データベース OrientDB を使ってみる #2
データ間の関連(リレーション)について紹介します
データ間の関連とは2つの異なるレコードを関連付けることで、データの透過的な参照や複雑なデータ構造の表現が可能となります
OrientDB では参照型( Referenced relationships )と組込型( Embedded relationships )という2種類の関連付けをサポートしています
参照型は、フィールドに対象レコードのレコードID(全レコードにてユニークとなるID)を持つことでデータ間の関連付けを行います
そのため、関連付ける各レコードは独立したレコードとして各々参照できる必要があります
対して組込型は、フィールドに直接レコードをそのものを設定するもので、組み込まれたレコードを独立して参照することはできません
また、参照、組込型として関連付けられるデータは 1:1 だけでなく、各々 List 、 Set 、 Map という 1:N 、または N:M の関係を作ることができます
(今回はこの部分の説明の詳細は省略させて頂きます)
それでは実際にデータの登録を行い、どのような構造のレコードが生成されるかを説明したいと思います
今回使用した環境は下記の通りです
・Mac OS X 10.6.7
・Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326)
・OrientDB 0.9.25
・NetBeans 7.0 RC2
以降は上記環境にて、サーバの起動、専用クライアント(コンソール)の接続まで完了している前提で進めます
サーバやクライアントの起動方法、クライアントを使用したレコード操作などについては、前々回のエントリを参照ください
また、文中で使われるレコードIDは環境により異なりますので、お使いの環境にあわせて読み替えてください
まず、テストデータを登録するため、下記クエリを実行して Person クラスと Group クラスを作成します
( ">" はプロンプトとなりますので、コピーして実行する際にはご注意ください)
> create class Person次に Group クラス のデータを登録します
> create class Group
> insert into Group (name) values ('Rebel Alliance')下記コマンドで Group クラスに2レコード登録されたことが確認できます
> insert into Group (name) values ('Galactic Empire')
> browse class Group"REC ID" は先の説明のレコードIDを指し、 "Rebel Alliance" は "25:0" 、 "Galactic Empire" は "25:1" のレコードIDを持つこととなります
---+--------+--------------------
#| REC ID |NAME
---+--------+--------------------
0| 25:0|Rebel Alliance
1| 25:1|Galactic Empire
---+--------+--------------------
次に参照型の関連フィールドを持つレコードを作成します
関連付けるレコードは先ほど登録した Group クラスのレコードです
下記クエリを実行して、 レコードを登録します
> insert into Person (name, surname, group) values ('Luke', 'Skywalker', 25:0)レコードに関連付けを設定する場合は、フィールドに対象のレコードIDを直接記述します
> insert into Person (name, surname, group) values ('Han', 'Solo', 25:0)
> insert into Person (name, group) values ('Chewbacca', 25:0)
> insert into Person (name, surname, group) values ('Leia', 'Organa', 25:0)
> insert into Person (name, group) values ('Darth Sidious', 25:1)
> insert into Person (name, group) values ('Darth Vader', 25:1)
(そのため、事前に関連づけるレコードIDを知っておく必要があります)
上記の場合、 "group" というフィールドにレコードIDを設定しており、これで Person クラスと Group クラスの各レコードが関連付けられることとなります
下記コマンドで Person クラスに6レコード登録されたことが確認できます
> browse class Person関連付けられたレコードに対しては、「フィールド名.対象レコードのフィールド名」の形式で指定することで値を参照することができます
---+--------+--------------------+--------------------+--------------------
#| REC ID |NAME |SURNAME |GROUP
---+--------+--------------------+--------------------+--------------------
0| 24:0|Luke |Skywalker |25:0
1| 24:1|Han |Solo |25:0
2| 24:2|Chewbacca |null |25:0
3| 24:3|Leia |Organa |25:0
4| 24:4|Darth Sidious |null |25:1
5| 24:5|Darth Vader |null |25:1
---+--------+--------------------+--------------------+--------------------
以下は select 文にて group フィールドに関連付けられた、 Group クラスの name フィールドを参照しています
(where 句にある "@rid" はレコードIDを意味するレコード属性になります)
> select name, surname, group.name from Person where @rid = 24:0また、他のフィールドと同様に where 句の検索条件としても使用できます
---+--------+--------------------+--------------------+--------------------
#| REC ID |NAME |SURNAME |GROUP
---+--------+--------------------+--------------------+--------------------
0| -1:-1|Luke |Skywalker |Rebel Alliance
---+--------+--------------------+--------------------+--------------------
> select from Person where group.name = 'Rebel Alliance'Java API を利用する場合、参照型レコードの登録は以下のようになります
---+--------+--------------------+--------------------+--------------------
#| REC ID |NAME |SURNAME |GROUP
---+--------+--------------------+--------------------+--------------------
0| 24:0|Luke |Skywalker |25:0
1| 24:1|Han |Solo |25:0
2| 24:2|Chewbacca |null |25:0
3| 24:3|Leia |Organa |25:0
---+--------+--------------------+--------------------+--------------------
(import 文、パッケージ名は省略しますのでご注意下さい)
public class Main {上記では Group クラスに1レコード登録、Rank クラスの新規作成と3レコード登録、 Person クラスに3レコード登録しています
public static void main(String[] args) {
// admin ユーザでサーバーの demo データベースに接続します
ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
// 新規レコード(Group)の作成
ODocument jediOrder = new ODocument(database, "Group");
jediOrder.field("name", "Jedi Order");
jediOrder.save();
// ユニークIDを取得
ORID jediOrderORID = jediOrder.getIdentity();
// 新規レコード(Rank)の作成
ODocument master = new ODocument(database, "Rank");
master.field("name", "Jedi Master");
master.save();
// ユニークIDを取得
ORID masterOrderORID = master.getIdentity();
ODocument knight = new ODocument(database, "Rank");
knight.field("name", "Jedi Knight");
knight.save();
// ユニークIDを取得
ORID knightOrderORID = knight.getIdentity();
ODocument padawan = new ODocument(database, "Rank");
padawan.field("name", "Padawan");
padawan.save();
// ユニークIDを取得
ORID padawanOrderORID = padawan.getIdentity();
// 新規レコード(Person)の作成
ODocument yoda = new ODocument(database, "Person");
yoda.field("name", "Yoda");
yoda.field("group", jediOrderORID);
yoda.field("rank", masterOrderORID);
yoda.save();
ODocument obiwan = new ODocument(database, "Person");
obiwan.field("name", "Obi-Wan");
obiwan.field("surname", "Kenobi");
obiwan.field("group", jediOrderORID);
obiwan.field("rank", knightOrderORID);
obiwan.save();
ODocument ahsoka = new ODocument(database, "Person");
ahsoka.field("name", "Ahsoka");
ahsoka.field("surname", "Tano");
ahsoka.field("group", jediOrderORID);
ahsoka.field("rank", padawanOrderORID);
ahsoka.save();
// 接続の解除
database.close();
}
}
参照型の関連付けを行う方法はクエリを使用したケースと同様にフィールドにレコードIDを設定します
Java API にてレコードID( Java API では ORID クラスにて表現されています)を取得するには、ODocument クラスの getIdentity() メソッドを使用します
なお、新規レコードの場合、事前に save() メソッドを呼び出してデータベースに登録が完了していないとレコードIDは取得できませんので、ご注意ください
レコードを取得する場合は下記のようになります
public class Main {上記を実行すると、以下のように値が取得できます
public static void main(String[] args) {
// admin ユーザでサーバーの demo データベースに接続します
ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
System.out.println("-----レコードIDを指定してレコードを取得-----");
// RID=24:6(Yoda) を取得
ODocument yoda = new ODocument(database, new ORecordId(24, 6));
// group フィールドを取得
ODocument yodaGroup = yoda.field("group");
Object yodaGroupName = yodaGroup == null ? "" : yodaGroup.field("name");
// rank 1フィールドを取得
ODocument yodaRank = yoda.field("rank");
Object yodaRankName = yodaRank == null ? "" : yodaRank.field("name");
// 取得レコードの出力
System.out.println("name : " + yoda.field("name"));
System.out.println("surname: " + yoda.field("surname"));
System.out.println("group : " + yodaGroupName);
System.out.println("rank : " + yodaRankName);
System.out.println();
System.out.println("-----クエリを実行してレコードを取得-----");
// SELECT 文を作成する
String selectQuery = "select from Person where group.name = 'Jedi Order' ";
// クエリを実行する
List<ODocument> people = database.query(new OSQLSynchQuery<ODocument>(selectQuery));
for (ODocument person : people) {
// group フィールドを取得
ODocument group = person.field("group");
Object groupName = group == null ? "" : group.field("name");
// rank 1フィールドを取得
ODocument rank = person.field("rank");
Object rankName = rank == null ? "" : rank.field("name");
// 取得レコードの出力
System.out.println("name : " + person.field("name"));
System.out.println("surname: " + person.field("surname"));
System.out.println("group : " + groupName);
System.out.println("rank : " + rankName);
System.out.println();
}
// 接続の解除
database.close();
}
}
-----レコードIDを指定してレコードを取得-----
name : Yoda
surname: null
group : Jedi Order
rank : Jedi Master
-----クエリを実行してレコードを取得-----
name : Yoda
surname: null
group : Jedi Order
rank : Jedi Master
name : Obi-Wan
surname: Kenobi
group : Jedi Order
rank : Jedi Knight
name : Ahsoka
surname: Tano
group : Jedi Order
rank : Padawan
次に組込型の関連付けですが、現在(2011年4月12日時点)のバージョンではクエリによる組込型のレコードの登録、更新(参照は可能です)は対応しておらず、 Java API でのみとなります
Java API を利用する場合の登録は以下のようになります
public class Main {上記では Weapon クラスのレコードを1件作成し、 Person クラスのレコードの "weapon" フィールドに設定しています
public static void main(String[] args) {
// admin ユーザでサーバーの demo データベースに接続します
ODatabaseDocumentTx database = new ODatabaseDocumentTx("remote:localhost/demo").open("admin", "admin");
// 新規レコードを作成
ODocument lightsaber = new ODocument(database, "Weapon");
lightsaber.field("name", "Lightsaber");
lightsaber.field("type", "sword");
// RID=24:0(Luke) を取得
ODocument luke = new ODocument(database, new ORecordId(24, 0));
luke.field("weapon", lightsaber, OType.EMBEDDED);
luke.save();
database.close();
}
}
参照型と大きく異なる点は作成した Weapon クラスの save()メソッドを呼び出していない点、取得した Person クラスの "weapon" フィールドに設定する際、第3引数に "OType.EMBEDDED" を設定している点です
レコードの参照方法に関しては、組込型も参照型も差異はありません
> select from Person where @rid = 24:0参照型のフィールド "group" にはレコードIDの値("25:0")が設定されているのに対し、組込型は直接レコードが設定されているため、レコードIDは設定されていません
---+--------+--------------------+--------------------+--------------------+--------------------
#| REC ID |NAME |WEAPON |SURNAME |GROUP
---+--------+--------------------+--------------------+--------------------+--------------------
0| 24:0|Luke |-1:-1 |Skywalker |25:0
---+--------+--------------------+--------------------+--------------------+--------------------
組込まれたレコードのフィールドも同様の形式で参照可能です
> select name, surname, weapon.name, weapon.type from Person where @rid = 24:0以上が OrientDB の関連付けの機能の紹介と利用方法になります
---+--------+--------------------+--------------------+--------------------+--------------------
#| REC ID |NAME |WEAPON |SURNAME |WEAPON2
---+--------+--------------------+--------------------+--------------------+--------------------
0| -1:-1|Luke |Lightsaber |Skywalker |sword
---+--------+--------------------+--------------------+--------------------+--------------------
次回は、 OrientDB のグラフデータベースとしての機能を紹介したいと思います
(次はあまり期間をあけないようしたいと思います…)