#ドキュメントデータモデル(NoSQL)

0 フォロワー · 2 投稿

ドキュメント指向のデータベース、つまりドキュメントストアは、半構造化データとも呼ばれるドキュメント指向の情報を格納、取得、および管理するために設計されたコンピュータープログラムです。 ドキュメント指向データベースの詳細をご覧ください。

記事 Toshihiko Minamoto · 9月 30, 2021 16m read

はじめに

Caché 2016.2のフィールドテストはかなり前から利用可能ですので、このバージョンで新しく追加されたドキュメントデータモデルという重要な機能に焦点を当てたいと思います。 このモデルは、オブジェクト、テーブル、および多次元配列など、データ処理をサポートするさまざまな方法として自然に追加されました。 プラットフォームがより柔軟になるため、さらに多くのユースケースに適したものになります。

いくつかのコンテキストから始めましょう。 NoSQLムーブメントの傘下にあるデータベースシステムを少なくとも1つは知っているかもしれません。 これにはかなりたくさんのデータベースがあり、いくつかのカテゴリにグループ化することができます。 Key/Valueは非常に単純なデータモデルです。 値をデータベースに格納し、それにキーを関連付けることができます。 値を取得する場合は、キーを介してそれにアクセスする必要があります。 適切なキーを選択によってソートが決まり、キーの一部であるものでグループ化する場合に単純な集計に使用できるようになるため、キーの選択が重要な鍵となります。 ただし、値は値にすぎません。 値内の特定のサブ要素にアクセスしたり、それらにインデックスを作成したりすることはできません。 値をさらに活用するには、アプリケーションロジックを書く必要があります。 Key/Valueは、大規模なデータセットと非常に単純な値を操作する必要がある場合に最適ですが、より複雑なレコードを扱う場合には価値が劣ります。

ドキュメントデータモデルはKey/Valueにとてもよく似ていますが、値はより複雑です。 値はキーに関連付けられたままになりますが、さらに、値のサブ要素にアクセスして特定の要素にインデックスを作成することができます。 つまり、いくつかのサブ要素が制限を満たす特定のドキュメントを検索することもできるということです。 明らかに、NoSQLの世界にはGraphのような他のモデルもさらに存在しますが、ここでは、ドキュメントに焦点を置くことにします。

 

そもそもドキュメントとは?

一部の読者を混乱させる傾向があるため、まず最初に、1つ明確にしておきましょう。この記事で「ドキュメント」と言った場合、PDFファイルやWordドキュメントといった物理的なドキュメントを指してはいません。
この文脈でのドキュメントとは、サブ値を特定のパスと関連付けることのできる構造を指しています。 ドキュメントを記述できるシリアル化形式には、JSONやXMLなどのよく知られたものが様々あります。 通常こういった形式には、共通して次のような構造とデータ型があります。

  1. 順序付けされていないKey/Valueペアの構造
  2. 順序付けされた値のリスト
  3. スカラー値

1つ目は、XMLの属性要素とJSONのオブジェクトにマッピングされます。 2つ目の構造は、XMLのサブ要素とJSONの配列を使ったリストによって導入されています。 3つ目は、単に、文字列、数値、ブール値といったネイティブのデータ型を利用できるようしています。

JSONのようなシリアル化された形式でドキュメントを視覚化することは一般的ですが、これは、ドキュメントを表現できる一方法にすぎないことに注意してください。 この記事では、JSONを主なシリアル化形式として使用することにします。JSONサポートの改善機能をうまく利用できるでしょう。この改善についてまだ読んでいない方はこちらをご覧ください。

ドキュメントはコレクションにグループ化されます。 セマンティックと潜在的に共通の構造を持つドキュメントは同じコレクションに保存する必要があります。 コレクションはその場で作成できるため、事前にスキーマ情報を用意しておく必要はありません。

コレクションにアクセスするには、データベースハンドルを最初に取得しておく必要があります。 データベースハンドルはサーバーへの接続として機能し、コレクションへの単純なアクセスを提供しますが、分散環境の場合にはさらに複雑なシナリオを処理することもできます。

 

基本

まず、Caché Object Scriptで単純なドキュメントを挿入する方法を見てみましょう。

USER>set db = ##class(%DataModel.Document.Database).$getDatabase()

USER>set superheroes = db.$getCollection("superheroes")

USER>set hero1 = {"name":"Superman","specialPower":"laser eyes"}

USER>set hero2 = {"name":"Hulk","specialPower":"super strong"}

USER>do superheroes.$insert(hero1)

USER>do superheroes.$insert(hero2)

USER>write superheroes.$size()
2

上記のコードサンプルでは、まずデータベースハンドルが取得されて、「superheroes」というコレクションが取得されます。 コレクションは明示的に作成されるため、事前に設定する必要はありません。 新しいコレクションにアクセスできるようになったら、ヒーローのSupermanとHulkを表す非常に単純なドキュメントを2つ作成します。 これらは$insert(<document>)への呼び出しでコレクションに保存され、コレクションサイズの最終チェックで、2つのドキュメントを報告します。これは、以前にコレクションが存在していなかったためです。

$insert()呼び出しは、成功すると、挿入されたドキュメントを返します。 このため、ドキュメントの操作を続行する場合に、自動的に割り当てられたIDを取得することができます。 また、チェーンメソッドも可能になります。

USER>set hero3 = {"name":"AntMan","specialPower":"can shrink and become super strong"}

USER>write superheroes.$insert(hero3).$getDocumentID()
3

このコードスニペットは、別のヒーローオブジェクトを作成し、superheroesコレクションに永続させます。 今回は、メソッド呼び出しの$getDocumentID()$insert()呼び出しに連鎖させ、システムがこのドキュメントに割り当てたIDを取得します。 $insert()は必ず自動的にIDを割り当てます。 独自のIDを割り当てる必要がある場合は、$insertAt(<User-ID>,<document>)呼び出しを利用できます。

特定のIDでドキュメントを取得する場合は、コレクションに対して$get(<ID>)メソッドを呼び出すことができます。

USER>set antMan = superHeroes.$get(3)

USER>write antMan.$toJSON()
{"name":"AntMan","specialPower":"can shrink and become super strong"}

Supermanとそのhometownを表すドキュメントを更新するとしましょう。 この場合、$upsert(<ID>,<document>)呼び出しを使用して、既存のドキュメントを簡単に更新することができます。

USER>set hero1.hometown = "Metropolis"

USER>do superheroes.$upsert(1,hero1)

USER>write superheroes.$get(1).$toJSON()
{"name":"Superman","specialPower":"laser eyes","hometown":"Metropolis"}

$upsert()は、IDがまだほかに使用されていない場合にドキュメントを挿入するか、そうでない場合に既存のドキュメントを更新します。
もちろん、$toJSON()を呼び出すだけで、コレクションの全コンテンツをJSONにシリアル化することも可能です。

USER>write superheroes.$toJSON()
[
{"documentID":1,"documentVersion":4,"content":{"name":"Superman","specialPower":"laser eyes","hometown":"Metropolis"}},
{"documentID":2,"documentVersion":2,"content":{"name":"Hulk","specialPower":"super strong"}},
{"documentID":3,"documentVersion":3,"content":{"name":"AntMan","specialPower":"can shrink and become super strong"}}
]

コレクションがドキュメントの配列として表されていることがわかります。 各ドキュメントは、ドキュメントIDとドキュメントバージョンでラップされており、同時実行を適切に処理するために使用されます。 実際のドキュメントコンテンツは、ラッパーのプロパティコンテンツに格納されます。 これは、コレクションの完全なスナップショットを取得して移動できるようにするために必要な表現です。
また、これはモデルの非常に重要な側面をカバーしており、特殊プロパティを予約してドキュメントデータに挿入することはありません。 ドキュメントを適切に処理するためのエンジンが必要とする情報は、ドキュメントの外部に保存されます。  さらに、ドキュメントはオブジェクトまたは配列のいずれかです。 その他の多くのドキュメントストアは、オブジェクトを最上位の要素としてのみ許可しています。

コレクションでドキュメントを変更するためのAPI呼び出しには他にもたくさんあり、基本的な演算をいくつか見てきました。 ドキュメントの挿入と変更は楽しい作業ですが、実際にデータセットを分析したり、特定の制限を満たすドキュメントを取得したりすると、さらに興味深くなります。 

 

クエリ

すべてのデータモデルが有用とみなされるには、何らかのクエリ機能が必要です。  動的スキーマを使用してドキュメントをクエリできるようにするには、2つの潜在的な方法があります。

  1. 動的なドキュメントの性質に対処できる独自のクエリ言語を設計して実装する
  2. 定着している構造化されたクエリ言語にクエリを統合する

この記事の後の方で説明するいくつかの理由により、コレクションをSQLエンジンに公開することにしました。 SQLの知識を引き続き活用できるというメリットがあります。また、クエリ方言の別のフレーバーを作成しているところでもあります。 実際、SQL ANSI委員会は、JSONの標準拡張機能を提案しており、それに準拠しています。 まとめれば、これらの拡張機能には、JSON関数の2つのカテゴリが含まれています。

  1. リレーションコンテンツからJSONコンテンツに公開するための関数セット
  2. 動的JSONコンテンツをクエリするための関数セット 

この記事の範囲では、2つ目のカテゴリである動的JSONコンテンツのクエリのみを取り上げ、結果をSQLで処理できるようにテーブルとして利用できるようにします。

動的コンテンツ(関連するスキーマのないコンテンツ)を公開し、事前に定義されたスキーマを使用してデータを操作するSQLで利用できるようにする魔法の関数は、JSON_TABLEです。 一般に、この関数は2つの引数を取ります。

  1. JSONデータソース
  2. 名前と型で列へのJSONパスのマッピングを指定する定義

骨に肉付けした例を見てみましょう。

SELECT name, power FROM JSON_TABLE(
  'superheroes',
  '$' COLUMNS(
    name VARCHAR(100) PATH '$.name',
    power VARCHAR(300) PATH '$.specialPower'
  )
)

name        power
---------   -------------------------------
Superman    laser eyes
Hulk        super strong
AntMan      can shrink and become super strong

JSON_TABLE関数の最初の引数は、それが作成する仮想テーブルのソースを定義します。 この場合、コレクション「superheroes」をクエリします。 このコレクションのドキュメントごとに行が作られます。
2つ目の引数は、ドキュメントの特定の値をテーブルの列として公開することを忘れないでください。 この引数は2つ部分で構成されています。最初のステップとして、次の式のコンテキストを設定します。 ドル記号'$'には特別な意味があり、ドキュメントのルートを指しています。 それ以降のすべての式はこのコンテキストを基準としています。
後に続くのは、COLUMNS句で、カンマ区切りのCOLUMN式のリストです。 COLUMN式ごとに、仮想テーブルの列が作成されます。 「name」と「power」という2つの列をクエリで公開しています。 列「name」はVARCHAR(100)型で定義されていますが、列「power」は300文字に制限されています。 PATH式は、JPL(JSONパス言語)式を使用してドキュメントの特定の値を列に関連付けています。 キー「name」の値は列「name」に公開されますが、キー「specialPower」の値は列「power」にマッピングされます。 JPL式は非常に表現力が高く強力ですが、これについては別のトピックで説明することにします。 このサンプルで使用した式は非常に基本的な式です。

この構文が初めてであれば、理解するのに少し時間が掛かるかもしれませんが、 JSON_TABLE関数を自然に読み取ると理解しやすいでしょう。 例として、上記のクエリを使います。 ここで表現しているのは、基本的に次のことです。

コレクション「superheroes」をクエリし、各ドキュメントのルートに式のコンテキストを設定します。 次の2つの列を公開します。

  1. 列「name」を型VARCHAR(100)で公開し、キー「name」の値を挿入します。
  2. 列「power」を型VARCHAR(300)で公開し、キー「specialPower」の値を挿入します。

前に述べた通り、JPL式は複雑になりがちであるか、たくさんの列を公開したいだけの場合もあります。 そのため、型定義を参照できる標準への拡張を組み込みました。これは基本的に、事前定義済みのCOLUMNS句です。 このようにして、上記のCOLUMNS句を登録することができます。

do db.$createType("heropower",{"columns":[{"column":"name","type":"VARCHAR(100)","path":"$.name"},{"column":"power","type":"VARCHAR(300)","path":"$.specialPower"}]})

型情報を登録したら、%TYPE式を使って、JSON_TABLE関数でそれを参照することができます。

SELECT name, power FROM JSON_TABLE(
  'superheroes',
  '$' %TYPE 'heropower'
)

これは明らかに、SQLクエリにドキュメントの一貫したビューを提供し、クエリそのものを大幅に簡略化する上で役立ちます。

高度な内容

ここまで説明したことのほぼすべてについて補足することはたくさんありますが、ここでは最も重要なことに焦点を当てたいと思います。 最後のセクションを読みながら、JSON_TABLE関数を非常に強力なポイントとしている手掛かりに気づいたかもしれません。 

  1. 仮想テーブルを作成する
  2. JSONのようなデータをソースデータとして消費できる

最初の項目はそれだけで重要なポイントです。コレクションを簡単にクエリして、別のJSON_TABLE呼び出しまたは正にテーブルと結合することができるからです。 コレクションをテーブルと結合できることは大きなメリットです。要件に応じて、データに完璧なデータモデルを選択できるのです。 
型安全、整合性チェックが必要であるのに、モデルがあまり進化していませんか? リレーショナルを使いましょう。 他のソースのデータを処理してそのデータを消費する必要があり、モデルが必ず急速に変化するか、アプリケーションユーザーの影響を受ける可能性のあるモデルを保存することを検討していますか? ドキュメントデータモデルを選択しましょう。 モデルはSQLで一緒にまとめることができるので安心です。

JSON_TABLE関数の2つ目のメリットは、実のところ基盤のデータモデルとは無関係です。 これまでに、JSON_TABLEでコレクションのクエリを説明してきました。 最初の引数は任意の有効なJSON入力にすることもできます。 次の例を考察しましょう。

SELECT name, power FROM JSON_TABLE(
  '[
    {"name":"Thor","specialPower":"smashing hammer"},
    {"name":"Aquaman","specialPower":"can breathe underwater"}
  ]',
  '$' %TYPE 'heropowers'
)

name        power
---------   -------------------------------
Thor        smashing hammer
Aquaman     can breathe underwater

入力は通常のJSON文字列で、オブジェクトの配列を表します。 構造がsuperheroesコレクションと一致するため、保存された型識別子「heropowers」を再利用することができます。 
これにより、強力なユースケースが可能になります。 実際にメモリ内のJSONデータをディスクに永続させずにクエリすることができます。 REST呼び出しでJSONデータをリクエストし、クエリを実行してコレクションまたはテーブルを結合できます。 この機能を使用すると、Twitterタイムライン、GitHubリポジトリの統計、株式情報、または単に天気予報のフィードをクエリできます。 この機能は非常に便利であるため、これについては、後日、専用の記事で取り上げたいと思います。

 

REST対応

ドキュメントデータモデルでは、初期状態でREST対応のインターフェースが備わっています。 すべてのCRUD(作成、読み取り、更新、削除)とクエリ機能はHTTP経由で利用できます。 完全なAPIについては説明しませんが、ネームスペース「USER」内の「superheroes」コレクションのすべてのドキュメントを取得するサンプルcURLを以下に示します。

curl -X GET -H "Accept: application/json" -H "Cache-Control: no-cache" http://localhost:57774/api/document/v1/user/superheroes

 

私のユースケースで使用できますか?

ドキュメントデータモデルは、InterSystemsのプラットフォームへの重要な追加機能です。 これは、オブジェクトとテーブルに続く、まったく新しいモデルです。 SQLとうまく統合できるため、既存のアプリケーションで簡単に利用することができます。 Caché 2016.1で導入された新しいJSON機能によって、CachéでのJSONの処理が楽しく簡単になります。

そうは言っても、これは新しいモデルです。 いつ、そしてなぜそれを使用するのかを理解する必要があります。 常に言っていることですが、特定のタスクにはそれに適したツールを選択してください。

このデータモデルは、動的データを処理する必要がある場合に優れています。 以下に、主な技術的メリットをまとめます。

  • 柔軟性と使いやすさ

スキーマを予め定義する必要がないため、データの作業環境を素早くセットアップし、データ構造の変更に簡単に適応させることができます。

  • スパース性

テーブルに300列があっても、各行が入力できるのはその内の15列であることを覚えていますか? これはスパースなデータセットであり、リレーショナルシステムではそれらを最適に処理にできません。 ドキュメントは設計上スパースであり、効率的に保存と処理を行えるようになっています。

  • 階層

配列やオブジェクトなどの構造化型は、任意の深さでネストすることができます。 つまり、ドキュメント内で関連するデータを保存することができるため、そのレコードにアクセスする必要がある場合の読み取りのI/Oを潜在的に縮小することができます。 データは非正規化して保存できますが、リレーショナルモデルではデータは正規化して保存されます。

  • 動的な型

特定のキーには、列のように固定されたデータ型がありません。 名前は、あるドキュメントでは文字列であっても、別のドキュメントでは複雑なオブジェクトである可能性があります。 単純なものは単純にしましょう。 複雑になることはありますが、そうなった場合はもう一度単純化しましょう。

上記の項目はそれぞれ重要であり、適切なユースケースには、少なくとも1つが必要ではありますが、すべての項目が一致することは珍しいことではありません。

モバイルアプリケーションのバックエンドを構築しているとしましょう。 クライアント(エンドユーザー)は自由に更新できるため、同時に複数のバージョンのインターフェースをサポートする必要があります。 WebServicesを使用するなど、契約によって開発すると、データインターフェースを素早く適応させる能力が低下する可能性があります(ただし、安定性が増す可能性はあります)。 ドキュメントデータモデルには柔軟性が備わっているため、スキーマを素早く進化させ、特定のレコード型の複数のバージョンを処理し、それでもクエリで相関させることができます。

 

その他のリソース

この魅力的な新機能についてさらに詳しく知りたい方は、利用可能なフィールドテストバージョン2016.2または2016.3を入手してください。

『ドキュメントデータモデル学習パス』を必ず確認してください。
https://beta.learning.intersystems.com/course/view.php?id=9

今年のグローバルサミットのセッションをお見逃しなく。 「データモデリングリソースガイド」には、関連するすべてのセッションが集められています。
https://beta.learning.intersystems.com/course/view.php?id=106

最後に、開発者コミュニティに参加し、質問を投稿しましょう。また、フィードバックもお待ちしています。

0
0 200
記事 Toshihiko Minamoto · 6月 15, 2021 11m read

MonCaché — InterSystems Caché での MongoDB API 実装

免責事項:この記事は筆者の私見を反映したものであり、InterSystemsの公式見解とは関係ありません。

構想

プロジェクトの構想は、クライアント側のコードを変更せずに MongoDB の代わりに InterSystems Caché を使用できるように、ドキュメントを検索、保存、更新、および削除するための基本的な MongoDB(v2.4.9) API 機能を実装するところにあります。

動機

おそらく、MongoDB に基づくインターフェースを使って、データストレージに InterSystems Caché を使用すると、パフォーマンスが向上するのではないか。 このプロジェクトは、学士号を取得するための研究プロジェクトとして始まりました。

ダメなわけないよね?! ¯\(ツ)

制限

この研究プロジェクトを進める過程で、いくつかの簡略化が行われました。

  • プリミティブ型のデータのみを使用する: nullbooleannumberstringarrayobjectObjectId
  • クライアント側のコードは MongoDB ドライバーを使って MongoDB と連携する。
  • クライアント側のコードでは、MongoDB Node.js ドライバーを使用する。
  • クライアント側のコードでは、MongoDB API の基本的な機能のみを使用する:
    • findfindOne — ドキュメントの検索
    • saveinsert — ドキュメントの保存
    • update — ドキュメントの更新
    • remove — ドキュメントの削除
    • count — ドキュメント数のカウント

実装

タスクは最終的に次のサブタスクに分割されました。

  • 選択した基本機能ように、MongoDB Node.js ドライバーのインターフェースを再作成する。
  • このインターフェースを InterSystems Caché を使用してデータストレージ用に実装する。
    • Caché でデータベースの表現スキームを設計する。
    • Caché でコレクションの表現スキームを設計する。
    • Caché でドキュメントの表現スキームを設計する。
    • Node.js を使って Caché と対話するためのスキームを設計する。
    • 設計したスキームを実装して、少しテストする。 :)

実装の詳細

最初のサブタスクは問題ではなかったので、中間の説明を省略して、インターフェースの実装部分を説明します。

MongoDB は、データベースをコレクションの物理的なコンテナとして定義します。 コレクションはドキュメントのセットで、ドキュメントはデータのセットです。 ドキュメントは JSON ドキュメントのようですが、大量の許容型を持っています。つまり BSON です。

InterSystems Caché では、すべてのデータはグローバルに保存されます。 簡単に言えば、階層データ構造として考えることができます。

このプロジェクトでは、すべてのデータは単一のグローバル(^MonCache )に保存されます。

そのため、階層データ構造を使用して、データベース、コレクション、およびドキュメントの表現スキームを設計する必要があります。

Caché におけるデータベースの表現スキーム

実装したグローバルレイアウトは、数多くの潜在的なレイアウトの 1 つに過ぎず、これらのレイアウトには、それぞれにメリットと制限があります。

MongoDB では、1 つのインスタンスに複数のデータベースが存在する可能性があるため、複数の分離されたデータベースを格納できるようにする表現スキームを設計する必要があります。 MongoDB はコレクションをまったく含まないデータベースをサポートしていることに注意しておきましょう(これらを「空」のデータベースと呼ぶことにします)。

私はこの問題に対し、一番単純で一番明白なソリューションを選択しました。 データベースは、^MonCache グローバルの第 1 レベルノードとして表されます。 さらに、そのようなノードは、「空」のデータベースのサポートを有効にするために ”” 値を取得します。 問題は、これを行わずに子ノードを追加するだけの場合、それらを削除すると親ノードも削除されるということです(これがグローバルの動作です)。

したがって、各データベースは Caché 内で次のように表されます。

^MonCache(<db>) = ""

たとえば、「my_database」データベースの表現は次のようになります。

^MonCache("my_database") = ""

Caché におけるコレクションの表現スキーム

MongoDB は、コレクションをデータベースの要素として定義します。 単一のデータベース内にあるすべてのコレクションには、正確なコレクションの識別に使用できる一意の名前があります。 このことが、グローバルでコレクションを表現する単純な方法を見つけ、第 2 レベルのノードを使用する上で役立ちました。 次に、2 つの小さな問題を解決する必要があります。 1 つ目の問題は、コレクションがデータベースと同じように空であることができるということです。 2 つ目は、コレクションが一連のドキュメントであるということです。 そして、これらのドキュメントはすべて、互いに分離している必要があります。 正直なところ、コレクションノードの値として自動的に増分する値のようなカウンターを使う以外に良いアイデアが浮かびませんでした。 すべてのドキュメントには一意の番号があります。 新しいドキュメントが挿入されると、現在のカウンターの値と同じ名前が付いた新しいノードが作成され、カウンターの値が 1 つ増加するというアイデアです。

したがって、各 Caché コレクションは、次のように表されます。

^MonCache(<db>) = ""
^MonCache(<db>, <collection>) = 0

たとえば、「 my_database」データベース内の「my_collection」コレクションは次のように表されます。

^MonCache("my_database") = ""
^MonCache("my_database", "my_collection") = 0

Caché におけるドキュメントの表現スキーム

このプロジェクトでは、ドキュメントは追加の ObjectID という型で拡張された JSON ドキュメントです。 ドキュメントの表現スキームは、階層データ構造で設計する必要がありました。 いくつかの驚きに遭遇したのはここです。 まず、Caché では「ネイティブ」の null がサポートされていなかったために、使用できなかったことです。 もう 1 つは、ブール値が 0 と 1 の定数で実装されているということです。 つまり、1 が true で 0 が false ということなのです。 一番予想していた問題は、ObjectId を格納する方法を考え出す必要があるということでした。 結局、これらの問題はすべて最も簡単な方法でうまく解決されたのです。というか、解決されたと思いました。 以下では、各データ型とその表現について説明します。

Caché のインタラクションスキーム

Node.js ドライバーの選択は、InterSystems Caché と連携する上で論理的かつ単純な決定であるように思われました(ドキュメントサイトには、Caché と対話するためのドライバーがほかにも掲載されています)。 ただし、ドライバーの機能では不十分です。 私が行いたかったのは、1 回のトランザクションで複数の挿入を実行することだったので、 Caché 側で MongoDB API をエミュレートするために使用される一連の Caché ObjectScript クラスを開発することにしました。

Caché Node.js ドライバーは、Caché クラスにアクセスできませんでしたが、Caché からプロフラム呼び出しを行うことができました。 このことから、小さなツールが作成されました。ドライバーと Caché クラスを繋ぐ、一種のブリッジです。

結局、スキームは次のようになりました。

プロジェクトの作業を進めながら、NSNJSON(Not So Normal JSON: あんまり普通じゃない JSON)と名付けた、ドライバーを介して ObjectId、null、true、および false を Caché に「密輸」する特別な形式を作成しました。 この形式の詳細については、GitHub の対応するページ(NSNJSON)をご覧ください。

MONCACHÉ の機能

ドキュメント検索には、次の基準を使用できます。

  • $eq — 等号
  • $ne — 不等号
  • $not — 否定
  • $lt — より小さい(未満)
  • $gt — より大きい
  • $exists — 有無、存在

ドキュメントの更新操作には、次の演算子を使用できます。

  • $set — 値の設定
  • $inc — 指定された数による増分
  • $mul — 指定された数による乗算
  • $unset — 値の削除
  • $rename — 値の名前変更

以下のコードは、私がドライバーの公式ページから取得して少し修正したコードです。

var insertDocuments = function(db, callback) {
 var collection = db.collection('documents');
 collection.insertOne({ site: 'Habrahabr.ru', topic: 276391 }, function(err, result) {
     assert.equal(err, null);
     console.log("Inserted 1 document into the document collection");
     callback(result);
 });
}
var MongoClient = require('mongodb').MongoClient
  , assert = require('assert');
var url = 'mongodb://localhost:27017/myproject';
MongoClient.connect(url, function(err, db) {
    assert.equal(null, err);
    console.log("Successfully connected to the server");
    insertDocument(db, function() {
         db.close();
     });
});

このコードは、MonCaché と互換性を持つように簡単に変更することができます。

ドライバーを変更するだけです!

// var MongoClient = require('mongodb').MongoClient
var MongoClient = require('moncache-driver').MongoClient

このコードが実行されると、^MonCache グローバルは次のようになります。

^MonCache("myproject","documents")=1
^MonCache("myproject","documents",1,"_id","t")="objectid"
^MonCache("myproject","documents",1,"_id","v")="b18cd934860c8b26be50ba34"
^MonCache("myproject","documents",1,"site","t")="string"
^MonCache("myproject","documents",1,"site","v")="Habrahabr.ru"
^MonCache("myproject","documents",1,"topic","t")="number"
^MonCache("myproject","documents",1,"topic","v")=267391

デモ

ほかのすべてとは別に、小型のデモアプリケーションソースコード)を公開しました。また、サーバーの再起動とソースコードの変更を行わないで、MongoDB Node.js から MonCaché Node.js へのドライバーの変更を実演するために、Node.js を使って実装しました。 アプリケーションは、CRUD 演算を製品やオフィスで実行するための小さなツールであり、構成を変更(ドライバーを変更)するためのインア―フェースでもあります。

サーバーでは、構成で選択されたストレージ(Caché または MongoDB)に保存される製品オフィスを作成できます。

Orders]タブには、注文のリストが含まれています。 レコードは作成されていますが、フォームは未完成です。 プロジェクトの援護を歓迎しています(ソースコード)。

構成は、Configuration ページで変更できます。 このページには、MongoDB と MonCache の 2 つのボタンがあります。 対応するボタンをクリックすると、希望する構成を選択できます。 構成が変更されると、クライアントアプリケーションはデータソースに再接続します(実際に使用されているドライバーからアプリケーションを分離する概念)。

まとめ

結論を出すために、根本的な質問に答えさせてください。 そうです! 基本的な操作におけるパフォーマンスを向上させることができました。

MonCaché プロジェクトは GitHub に公開されており、MIT ラインセンスの下に提供されています。

簡易マニュアル

  • Caché のインストール
  • 必要な MonCaché コンポーネントを Caché に読み込む
  • Caché で MONCACHE 領域を作成する
  • Caché で、ユーザー名が「moncache」でパスワードが「ehcacnom」(moncache」の逆)のユーザーを作成する
  • 環境変数 MONCACHE_USERNAME = moncache を作成する
  • 環境変数 MONCACHE_PASSWORD = ehcacnom を作成する
  • 環境変数 MONCACHE_NAMESPACE = MONCACHE を作成する
  • プロジェクトで、依存関係を 'mongodb' から 'moncache-driver' に変更する
  • プロジェクトを始動! :-)

InterSystems 教育プログラム

InterSystems テクノロジーに基づく独自の研究プロジェクトを始めたい方は、InterSystems 教育プログラム専用の特設サイトをご覧ください。

0
0 147