Java 開発 2.0: MongoDB: (適切なすべての) RDBMS の動作をする NoSQL データ・ストア

Java コードと Groovy を使用して文書を作成し、その文書に対してクエリーを実行する

NoSQL データベースの世界を探っているとしたら、NoSQL RDBMS とも称される MongoDB を調査の対象に含める価値はあります。この記事では MongoDB がサポートしているカスタム API、対話型シェル、RDBMS 方式の動的クエリー、素早く簡単な MapReduce による計算について説明します。さらに、MongoDB のネイティブ Java™ 言語のドライバーと便利な Groovy ラッパーである GMongo を使ってデータを作成、検索、操作する方法も紹介します。

Andrew Glover, Author and developer, Beacon50

Andrew GloverAndrew Glover は、ビヘイビア駆動開発、継続的インテグレーション、アジャイル・ソフトウェア開発に情熱を持つ開発者であるとともに、著者、講演者、起業家でもあります。また、easyb BDD (Behavior-Driven Development) フレームワークの創始者、そして『継続的インテグレーション入門 開発プロセスを自動化する47の作法』、『Groovy in Action』、『Java Testing Patterns』の 3 冊の本の共著者でもあります。詳細は彼のブログにアクセスするか、Twitter で彼をフォローしてください。



2010年 9月 28日

MongoDB や CouchDB などのドキュメント指向のデータベースは、データをテーブルに保管する代わりに、文書の形で保管するという点で、リレーショナル・データベースとは大きく異なります。開発者から見ると、ドキュメント指向 (つまり、スキーマレス) のデータのほうが扱いやすく、リレーショナル・データより遥かに柔軟に管理することができます。相互関係によって結合されたテーブル、行、列という厳格なスキーマにデータを保管するのではなく、それぞれに必要なデータを含めた文書を個別に作成できるからです。

MongoDB の作成者による解説

オープンソースの文書データベース MongoDB について、10gen の CTO である Eliot Horowitz が、このタイムリーな技術ポッドキャストで詳しく語っています。ここをクリックして聴いてください。

オープンソースのドキュメント指向データベースのなかでも MongoDB は、RDBMS の特徴を持つ NoSQL データベースであるとよく言われます。そのように言われる 1 つの理由として、MongoDB では事前定義された MapReduce 関数を必要としない動的クエリーをサポートしています。さらに、MongoDB にはデータ・ストアへのアクセスをこれまでになく容易にする対話型シェルや、複数のノードで高いスケーラビリティーを可能にするシャーディング機能も用意されています。

MongoDB の API は、JSON オブジェクトと JavaScript 関数をネイティブに組み合わせたものです。開発者が MongoDB を操作する際には、コマンド・ライン引数を使用できるシェル・プログラムが使われます。あるいは、言語ドライバーを使ってデータ・ストア・インスタンスにアクセスするという方法もあります。ただし、JDBC のようなドライバーはないので、ResultSetPreparedStatement を扱う必要はありません。

MongoDB には処理が高速であるという長所もあります。これは、MongoDB では書き込み処理を行う場合、いったんメモリーに保管した後に、バックグラウンド・スレッドでディスクに書き込むという方法を採っているからです。

この連載について

Java 技術が初めて登場してから現在に至るまでに、Java 開発の様相は劇的に変化しました。成熟したオープンソースのフレームワーク、そしてサービスとして提供される信頼性の高いデプロイメント・インフラストラクチャーを利用できる (借りられる) おかげで、今では Java アプリケーションを短時間かつ低コストでアセンブルし、テスト、実行、保守することが可能になっています。この連載では Andrew Glover が、この新たな Java 開発パラダイムを可能にする多種多様な技術とツールを詳しく探ります。

この記事では MongoDB について知ってもらうために、CouchDB を紹介する記事 (「参考文献」を参照) で使用した駐車違反切符を例に、スキーマレス・データ・ストレージの柔軟性を明らかにします。MongoDB の API と動的クエリーのサポートは、このデータベースの最大の長所です。そこで、記事ではこの 2 つに焦点を絞り、MongoDB のシェルと Java 言語ドライバーを使用したサンプル・コードを解説します。記事の後半では、GMongo についても紹介します。MongoDB の MapReduce 実装から冗長部分を除いたこの Groovy ラッパーも、MongoDB という NoSQL データベースの注目すべき点です。

スキーマレスを選ぶ理由とは

スキーマレスなストレージはすべてのドメインに適しているわけではありません。したがって、リレーショナル手法ではなくドキュメント指向を選択する理由を理解しておくとためになります。文書の柔軟性が意味を持つのは、データをさまざまな形で表現できる一方、基本モデルは変わらないというドメインです。その典型的な例には、名刺が挙げられます。名刺の束があるとすると、名刺によって記載されているデータが異なることがあります。ファックス番号や会社の URL が記載された名刺もあれば、メール・アドレスが記載されたもの、あるいは 2 つの電話番号や Twitter のハンドル名が記載された名刺もあるでしょう。記載されるデータは異なりますが、そのモデル、つまり役割はすべての名刺に共通しています。その役割とは、連絡先情報を記載することです。

名刺をリレーショナルの観点からモデル化するのは不可能ではないにせよ、複雑なモデルになります。最終的にリレーショナル・データベースでは、ファックスの列で値を使用するのは 1 つか 2 つのレコードだけで、残りの多数のレコードには null 値が含まれることになってしまうかもしれません。さらに、リレーショナル・システムでは列の型を指定しなければならないため、住所フィールドの長さの制約に引っかかる可能性もあります (例えば、Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch に住んでいる人の住所を保管するなどとは考えもしないでしょうが、この町は実際に存在します)。

ドキュメント指向のデータ・ストアで名刺をモデル化するのは、リレーショナル手法と比べると遥かに簡単です。スキーマがないということは、必要とされるどんなデータでも、長さに関係なく文書に保管できることを意味します。名刺が持つ性質を考えると、さまざまなプロパティーを持つ文書としてモデル化するのがふさわしいと言えます。

ほとんどの場合、スキーマレス・データ・ストアは ACID (アトミック性、一貫性、独立性、永続性) を完全にはサポートしません。この点は、信頼性と一貫性が鍵となるドメインでは問題になるはずです。その一方、NoSQL 手法の支持者たちは、ACID が功を奏するのはダウンタイムの発生を考慮しなくてよい場合に限られると主張します。ダウンタイムの発生は、スケーリングを目的に複数のノードを導入し始めるようになれば避けようがありません。結論としては、スキーマレス・データ・ストアはリレーショナル・データベースよりも容易にスケーリングできる傾向があることから、Web ベースのアプリケーションにはドキュメント指向のストレージが適しているということです。


MongoDB の導入

MongoDB を導入するのは、特にターゲット・オペレーティング・システム用のダウンロードが用意されていることから、これ以上ないほどに簡単です。例えば Mac OS X に MongoDB をセットアップするとしたら、Mac OS X 用のバイナリーをダウンロードして解凍し、データ・ディレクトリー (MongoDB がデータ・ストアの内容を書き込むディレクトリー) を作成してから mongodb コマンドでインスタンスを起動すればよいのです (このプロセスでは必ず、データの書き込み先を指定してください)。

リスト 1では、MongoDB を起動して、データの保管先を data/db ディレクトリーに指定しています。お気付きのように、このコマンドでは verbose フラグも指定しています。v の数が多ければ多いほど出力は詳細になります。

リスト 1. Mac OS X 用の MongoDB
iterm$ ./bin/mongod — dbpath ./data/db/ ——vvvvvvvv

MongoDB を起動すれば、その対話型シェルの使い方はすぐにつかめるはずです。何も指定せずに mongo コマンドを呼び出すと、リスト 2 のようなコードが表示されます。

リスト 2. MongoDB シェルを起動する
iterm$ ./bin/mongo
MongoDB shell version: 1.6.0
connecting to: test
>

シェルを起動すると、最初は test データ・ストアに接続されます。とりあえずはこのデータ・ストアを使用して、文書を作成および検索する方法を説明します。これには、JavaScript と JSON を作成する作業が含まれます。


文書の作成と検索

CouchDB と同様に、MongoDB では JSON で容易に文書を作成できるようにしています (ただし、文書は BSON として保管されます。これは、効率性を目的に利用される JSON のバイナリー形式です)。駐車違反切符を対話型シェルで作成するには、リスト 3 のように JSON 文書を作成するだけです。

リスト 3. 単純な JSON 文書
> ticket =  { officer: "Kristen Ree" , location: "Walmart parking lot", vehicle_plate: 
  "Virginia 5566",  offense: "Parked in no parking zone", date: "2010/08/15"}

リターン・キーを押すと、MongoDB がリスト 4 のようなフォーマットの JSON 文書でレスポンスを返します。

リスト 4. MongoDB のレスポンス
{
  "officer" : "Kristen Ree",
  "location" : "Walmart parking lot",
  "vehicle_plate" : "Virginia 5566",
  "offense" : "Parked in no parking zone",
  "date" : "2010/08/15"
}

上記で作成した駐車違反切符の JSON 表現には、ticket という名前を付けました。この文書を永続化するには、文書をコレクションに関連付ける必要があります。コレクションとは、リレーショナルで言うスキーマのようなものです。リスト 5 のコードでは、違反切符を tickets コレクションに関連付けます。

リスト 5. ticket インスタンスを保存する
> db.tickets.save(ticket)

MongoDB では、tickets コレクションを事前に作成する必要はなかったことに注意してください。コレクションは、初めて参照されるときに作成されます。

ここで、さらにいくつかの違反切符を作成しておいてください。次のセクションで文書を検索するときに、複数の文書があったほうがよいからです。

文書を検索する

コレクションに含まれるすべての文書を検索するのは簡単です。ただ単に、find コマンドを呼び出すだけのことです (リスト 6 を参照)。

リスト 6. MongoDB 内のすべての文書を検索する
> db.tickets.find()
{ "_id" : ObjectId("4c7aca17dfb1ab5b3c1bdee8"), "officer" : "Kristen Ree", "location" : 
  "Walmart parking lot", "vehicle_plate" : "Virginia 5566", "offense" : 
  "Parked in no parking zone", "date" : "2010/08/15" }
{ "_id" : ObjectId("4c7aca1ddfb1ab5b3c1bdee9"), "officer" : "Kristen Ree", "location" : 
  "199 Baldwin Dr", "vehicle_plate" : "Maryland 7777", "offense" : 
  "Parked in no parking zone", "date" : "2010/08/29" }

パラメーターが何も指定されていない find コマンドは、特定のコレクション (この例では tickets コレクション) に含まれるすべての文書を返します。

リスト 6 で注目すべき点は、_id キーによって示されているように、MongoDB が各文書の ID を作成していることです。

JSON 文書内では個々のキーを検索することができます。例えば Walmart (訳注: 米国に本社を置くスーパーマーケット・チェーン) の駐車場で発行されたすべての違反切符を検索するとしたら、リスト 7 のクエリーを使用します。

リスト 7. クエリーを使用して検索する
> db.tickets.find({location:"Walmart parking lot"})

JSON 文書内では、使用可能な任意のキーで検索することができます (この例の場合は offense_iddate など)。また別の検索方法として (リスト 8 を参照)、正規表現を使用してキーの値 (location など) を検索するという方法もあります。この場合の検索は、SQL の LIKE 文とほとんど同じように機能します。

リスト 8. 正規表現を使用して検索する
> db.tickets.find({location:/walmart/i})

正規表現文 (上記の例では、walmart というフレーズだけです) に続く末尾の i は、この文が大/小文字を区別しないことを意味します。


MongoDB の Java ドライバー

MongoDB の Java 言語ドライバーは、前のセクションに記載した JSON および JavaScript コードの大部分を抽象化することを意図して作られています。したがって開発者には、理解しやすい Java API が残されます。MongoDB の Java ドライバーを使用するには、このドライバーをダウンロードして、そこに含まれる .jar ファイルをクラス・パスに組み込むだけでよいのです (「参考文献」を参照)。

ここで、tickets コレクションに違反切符をもう 1 つ作成して、test データ・ストアに保管するとします。Java ドライバーを使用して違反切符を作成する場合、まず始めに MongoDB のインスタンスに接続し、それから test データベースと tickets コレクションを取得します (リスト 9 を参照)。

リスト 9. MongoDB の Java ドライバーを使用する
Mongo m = new Mongo();
DB db = m.getDB("test");
DBCollection coll = db.getCollection("tickets");

JSON 文書を Java ドライバーを使って作成するには、リスト 10 に示すように BasicObject を作成して名前と値を関連付けるだけでよいのです。

リスト 10. Java ドライバーを使用して文書を作成する
BasicDBObject doc = new BasicDBObject();

doc.put("officer", "Andrew Smith");
doc.put("location", "Target Shopping Center parking lot");
doc.put("vehicle_plate", "Virginia 2345");
doc.put("offense", "Double parked");
doc.put("date", "2010/08/13");

coll.insert(doc);

文書を検索して、検出されたカーソル・オブジェクトを繰り返し処理するのも、Java ドライバーによって至って簡単な操作になります (リスト 11 を参照)。

リスト 11. Java ドライバーを使用して文書を検索する
DBCursor cur = coll.find();
while (cur.hasNext()) {
 System.out.println(cur.next());
}

Groovy で行われる巧みな抽象化ライブラリーをはじめとする、Java ドライバーをベースに作成された多数のJava 開発者向け MongoDB ライブラリーが使用できるようになっています。次のセクションで作成するアプリケーションでは、デフォルトの Java ドライバーとそれよりも多少簡潔な Groovy ラッパー両方の使い方を具体的に見ることができます。さらに、この賢いアプリケーションは MongoDB の MapReduce 機能を使用して文書のコレクションを処理する方法も明らかにします。


MongoDB を使用した Twitter の分析

データベース内のデータそのものは、それほど興味深いものではありません。それをどのように利用するかによって、データは強力なものになります。このアプリケーションでは最初に Twitter から情報を取得し、それを MongoDB に保管した上で、2 つのメトリクスを計算します。メトリクスの 1 つは、私に最も頻繁にリツイートを返してきた Twitter ユーザー、そしてもう 1 つは、私のツイートのなかで最もリツイートが多かったツイートです。

このアプリケーションを実行するには何よりもまず、Twitter とインターフェースを取ってデータを取得するための手段がなければなりません。そこで、Twitter4J という巧みなライブラリーを使うことにします。Twitter4J を使用して Twitterの RESTful な API を単純な Java API に抽象化し (「参考文献」を参照)、この Java API を使用して私のリツイートを検索するという筋書きです。検索によって取得したデータは、リスト 12 に示すような JSON 文書のフォーマットにします。

リスト 12. JSON で保管されたリツイート
{ 
  "user_name" : "twitter user",
  "tweet" : "Podcast ...", 
  "tweet_id" :  9090...., 
  "date" : "08/12/2010" 
}

リスト13 では、私が作成した単純なドライバー・アプリケーション (これも Java コードで作成されています) で MongoDB のネイティブ Java ドライバーと併せて Twitter4J を使用して、データを取得した後、MongoDB に保管します。

リスト 13. MongoDB へ Twitter データを挿入する
Mongo m = new Mongo();
DB db = m.getDB("twitter_stats");
DBCollection coll = db.getCollection("retweets");

Twitter twitter = new TwitterFactory().getInstance("<some user name>", "<some password>");
List<Status> statuses = twitter.getRetweetsOfMe();
for (Status status : statuses) { 
  ResponseList<User> users = twitter.getRetweetedBy(status.getId());
  
  for (User user : users) {
    BasicDBObject doc = new BasicDBObject();
    doc.put("user_name", user.getScreenName());
    doc.put("tweet", status.getText());
    doc.put("tweet_id", status.getId());
    doc.put("date", status.getCreatedAt());
    coll.insert(doc);
 }
}

リスト 13twitter_stats データベースは、ドライバーが実行される時点ではまだ存在していないため、オンデマンドで作成されることに注意してください。これは、retweets コレクションにしても同じです。データベースとコレクションの両方が作成されると、Twitter4J の Twitter オブジェクトが取得され、続いて最新の 20 件のリツイートが取得されます。

これで、Twitter4J から返される Status オブジェクトの List は私のリツイートを表すことになります。各オブジェクトに対して関連データがクエリーされた後、MongoDB の BasicDBObject のインスタンスが作成されて、そこに関連データが取り込まれます。そして最後に文書のそれぞれが永続化されます。


MongoDB の MapReduce

データのすべてを保管し終わったので、次はデータを処理する作業に移ります。必要な情報を手に入れるには、2 つのバッチ処理が必要となります。まず、各 Twitter ユーザーがデータに含まれている回数を合計するという処理、続いて各 tweet (または tweet_id) が出現する回数を合計するという処理です。

MongoDB はバッチ・データ処理に MapReduce を活用します。大まかに言うと、MapReduce アルゴリズムは問題を 2 つのステップに分けます。最初のステップでは Map 関数を使用して、受け取った大きな入力データを小さなデータに分割し、そのデータを他のプロセスに渡して何らかの処理を行います。続くステップでは Reduce 関数を使用して、Map から返された個別の結果を 1 つの最終的な出力に集約します。

MongoDB のコア API は JavaScript なので、MapReduce 関数は JavaScript で作成しなければなりません。したがって、Java ドライバーを使っているとしても、MapReduce 関数には JavaScript を作成することになりますが、JavaScript は String あるいは BasicDBObject のようなオブジェクト内に定義することが可能です。さらに処理を単純化してコード作成の手間を省くため、ここでは MongoDB のデフォルト・ドライバーに小さなラッパー・ライブラリーを適用することにします。GMongo という名前のこのラッパーは Groovyで作成されていて、Groovy で使用するように意図されています。MapReduce 関数を JavaScript で作成しなければならないことに変わりはありませんが、Groovy は複数行文字列をサポートできるため、コードは多少簡潔になります。具体的には、文字列をエスケープする必要がなくなるということです。

JavaScript での MapReduce 関数

最も頻繁にリツイートを返してくる Twitter ユーザーを調べるには、2 つの作業が必要となります。最初の作業は、JSON 文書の構造に含まれる user_name プロパティーをキーに設定した map 関数を作成することです。この関数はリスト14 のとおり、かなり単純なものになります。

リスト 14. JavaScript で作成された単純な map 関数
function map() {
  emit(this.user_name, 1); 
}

上記の map 関数の内容は単純で、渡されたすべての文書の user_name プロパティーを取り込んでいるだけです。emit の呼び出しは必須です。emit の 2 番目の引数として取る値は、基本的にはキーの数であり、個別の文書の場合には 1 となります。この値がどのような役割を果たすのかは、この値を使用してすべてを合計するときにわかります。

このように、リスト 14 ではキー (user_name プロパティー) と値を使って emit 関数を呼び出しました。this 変数は、この関数のコンテキストでは JSON 文書そのものを表します。

次に必要な作業は、reduce 関数を定義することです (リスト 15 を参照)。この関数はグループ化されたすべての文書を引数に取り、その値を合計します。

リスト 15. JavaScript で作成された reduce 関数
function reduce(key, vals) {
  var sum = 0;
  for(var i in vals) sum += vals[i];
  return sum;
}

リスト 15 を見るとわかるように、reduce 関数に渡される key 変数と vals 変数は function reduce("asmith", [1,1,1,1]); のように表されます。これはもちろん、asmith という user_name が 4 つの異なる文書に出現していることを意味します。つまり、A. Smith は私に 4 回リツイートを返したということです!

このことは、vals 変数を繰り返し処理し、単純な sum が返されるようにすることで、確認することができます。

Groovy での MapReduce 関数

次に作成する Groovy スクリプトでは、GMongo を使用した後、前のセクションで作成した map 関数と reduce 関数を組み込みます (リスト 16 を参照)。

リスト 16. MapReduce のための Groovy スクリプト
  mongo = new GMongo()
def db = mongo.getDB("twitter_stats")

def res = db.retweets.mapReduce(
    """
    function map() {
        emit(this.user_name, 1); 
    }
    """,
    """
    function reduce(key, vals) {
        var sum = 0;
        for(var i in vals) sum += vals[i];
        return sum;
    }
    """,
    "result",
    [:] 
)

def cursor = db.result.find().sort(new BasicDBObject("value":-1))
       
cursor.each{
  println "${it._id} has retweeted you ${it.value as int} times"
}

リスト 16 では最初に GMongo のインスタンスを作成して、twitter_stats データ・ストアを取得します。この部分については、デフォルトの Java ドライバーを使用したとしてもほとんど変わりません。

次に、retweets コレクションで mapReduce メソッドを呼び出します。この場合、リスト 13 ではコレクションを取得しなければなりませんでしたが、GMongo ドライバーを使用すれば、コレクションを直接参照することができます。mapReduce メソッドが取る引数は 4 つあります。
最初の 2 つは、JavaScript で定義された map 関数と reduce 関数を表す String です。3 番目の引数は、MapReduce の結果を保持するオブジェクトの名前です。最後の引数には、処理を完了するために必要な任意の入力クエリーを指定することができます。例えば MapReduce 関数に、特定の JSON 文書 (特定の日付範囲内にある文書など)、あるいはその一部だけを渡すことも可能です。

続いて result オブジェクト (JSON 文書) に対してクエリーを実行し、sort 呼び出しを行います。リスト 16sort 呼び出しには、{value:-1} (最大の値を先頭に、逆順でソートすることを指定) のような JSON 文書が必要です。クエリーによって返された cursor オブジェクトは基本的にはイテレーターであるため、このオブジェクトで Groovy の便利な each を直接使用して、簡潔なレポートを出力することができます。出力されるレポートには、リツイート回数の多い順から Twitter ユーザーがリストアップされます。

リスト 16 のスクリプトを実行してみてください。すると、リスト 17 のような結果が出力されるはずです。

リスト 17. MapReduce の出力
bglover has retweeted you 3 times
bobama has retweeted you 3 times
sjobs has retweeted you 2 times
...

これで、私に最も頻繁にリツイートを返している Twitter ユーザーはわかりましたが、最も多くリツイートが返されたツイートを調べるにはどうすればよいのでしょうか。そのためのコードを作成するのは、ごく簡単です。user_name の代わりに、tweet プロパティーをキーに取るmap 関数を定義すればよいのです (リスト 18 を参照)。

リスト 18. もう 1 つの map 関数
function map() {
  emit(this.tweet, 1); 
}

さらに嬉しいことに、reduce 関数はグループ化されたキーを合計するだけなので、前のバージョンとまったく同じものを使用することができます。


まとめ

この記事では、ものすごい勢いで MongoDB の紹介をしたので、MongoDB で実現可能な内容について表面的に触れただけにすぎません。けれども、MongoDB はそのスキーマレスという性質によって、かなりの柔軟性を実現できるという点を理解していただけたことを願います。この柔軟性が特に役立つのは、記事の最初で取り上げた名刺の例のように、データの種類は多様ながらも大方は関連しているドメインです。

MongoDB と CouchDB はスキーマレスな柔軟性をサポートするという点では共通しますが、他の面ではかなりの違いがあります。MongoDB が持つ RDBMS のような特徴は、MongoDB を扱いやすいものにするだけでなく、RDBMS の視点から理解しやすいデータ・ストアにしています。MongoDB では動的なクエリーを実行して Java、Ruby、あるいは PHP などのネイティブ言語で処理をすることができます。しかもそれと同時に、MapReduce の能力を活用することができます。

ドキュメント指向のデータベースは、すべてのドメインに適しているというわけではありません。金融データを扱うトランザクションを多用するドメインには、ACID に関して信頼できる従来の RDBMS が最も適しているはずです。けれどもアプリケーションにハイパフォーマンスの処理能力、そして柔軟なデータ・モデルが必要だとしたら、MongoDB を調べてみる価値はあります。

参考文献

学ぶために

製品や技術を入手するために

  • MongoDB.org: MongoDB および Java 言語ドライバーをダウンロードしてください。
  • GMongo のダウンロード: デフォルトの Java 言語ドライバーの代わりとして使用できる Groovy ラッパーです。

議論するために

  • My developerWorks コミュニティーに加わってください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者が主導するブログ、フォーラム、グループ、ウィキを調べることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology
ArticleID=556051
ArticleTitle=Java 開発 2.0: MongoDB: (適切なすべての) RDBMS の動作をする NoSQL データ・ストア
publish-date=09282010