Share via


この記事は機械翻訳されたものです。

働くプログラマ

Cassandra NoSQL データベース (第 2 回): プログラミング (機械翻訳)

Ted Neward

 

Ted Neward2012 年 8 月のコラムで"カサンドラ NoSQL データベース。はじめに、「Apache カサンドラを検討しました。 それとして記載されている、"オープン ソース、分散、分散、弾性拡張性、高可用性、フォールト トレラント tuneably 一貫したその分布設計アマゾン ダイナモと Google Bigtable 上データ モデルに基づいて列指向データベース"本、"カサンドラ。決定的なガイド」(オライリー メディア、2010年)。 さらに正確に、私はカサンドラ (Java ベースのデータベースであるためこれは、Java 仮想マシンを取得し、すでに 1 つを持っていなかった場合あなたのマシンで実行しても必要です) をインストールする方法、コマンドラインからに接続する方法、およびそのデータ モデルのように見えた見た。 データ モデルは、ほとんどの開発者がよく知っているリレーショナル データベースよりも構造でかなり著しく異なるので繰り返し負いません。

最後の時間のとおり (msdn.microsoft.com/magazine/JJ553519)、カサンドラは保存する代わりに同じ組 (テーブル スキーマ) 固定構造に従って配置されたデータの構造と意味、「列指向」のデータ ストア、カサンドラ ショップ"keyspaces"の「列の家族」もっとわかりやすい用語では、カサンドラは、さまざまな数の別に 1 つの「行」から全く異なる可能性があります、名前/値ペア (列) をキー値を関連付けます。

たとえば、ので、さらに「地球最後の時間を作成」を考えると、列が「人」という名前の家族を書くつもりのロー (可能性がありますまたは可能性がありますいない) 次のような。

RowKey: tedneward
  ColumnName:"FirstName", ColumnValue:"Ted"
  ColumnName:"LastName", ColumnValue:"Neward"
  ColumnName:"Age", ColumnValue:41
  ColumnName:"Title", ColumnValue:"Architect"
RowKey: rickgaribay
  ColumnName:"FirstName", ColumnValue:"Rick"
  ColumnName:"LastName", ColumnValue:"Garibay"
RowKey: theartistformerlyknownasprince
  ColumnName:"Identifier", ColumnValue: <image>
  ColumnName:"Title", ColumnValue:"Rock Star"

見ることができますが、各「行」は、概念的に類似のデータが含まれているすべての「行」は、開発者やビジネスの特定の行の任意のキーを格納するために必要に応じて、同じデータがあります。 保存できなかったのでリックの年齢を知らない。 スキーマは、年齢が null 非許容列だと義務付けられて場合リレーショナル データベースでは、私はリックすべて保存しておくことができなかった。 カサンドラは言う、「どうして?」

私の前の列データの挿入と削除をコマンドラインから実証が、これは、目標にアクセスし、データを格納するアプリケーションを作成する場合に特に有用ではないです。 だから、さらに背景なし、レッツからの読み取りし、格納カサンドラを作成するアプリケーションに必要なものダイビングします。

カサンドラ, O カサンドラ、なぜカサンドラ アートなた?

開始するには、カサンドラに Microsoft .NET Framework から接続しなければ。 そう 2 つの手法の 1 つが含まれます。ネイティブの Apache 古道具 API を使用することができます。 またはサードパーティ製のラッパー古着のネイティブ API の上を使用することができます。 中古品は多くの類似点 (数年でそのことを考えていない賭け) DCOM または CORBA または .NET リモート処理にはバイナリ リモート プロシージャ呼び出しのツールキットです。 カサンドラとの通信、特に低レベルのアプローチは、倹約 c# をサポートしていますが、それすべてのことを取得するは簡単、実行されていません。 代替貯蓄を含める FluentCassandra、カサンドラ シャープ、Cassandraemon、アキレス ・ デレ (アキレスは、古代のギリシャ語のテーマは健在保つのスペイン語の翻訳)。 これらのすべてのオープン ソースは、カサンドラ API を介していくつかのよりよいの抽象化を提供します。 この列の FluentCassandra、使用しようとしているがそれらのいずれかにかなりよく奇数インターネット火炎戦争にかかわらず動作するように見えます。

開始する最も簡単な方法を NuGet パッケージ マネージャー (私は、調査テストを書くことができますので) Visual Studio テスト プロジェクトとは、「パッケージのインストール FluentCassandra」火に FluentCassandra、NuGet パッケージとして利用可能です。(この文書の執筆時点の最新バージョン 1.1.0 です)。行うと私はそれを 8 月列をおもちゃにした後、カサンドラ サーバーがまだ実行されていることをダブル チェックしました一度、探査の最初のテストを書くことができます。サーバーへの接続。

FluentCassandra 名前空間"FluentCassandra"と 2 つの入れ子になった名前空間 (「接続」と「種類」) に住んでいるので、私は、それらをもたらすとデータベースへの接続についてを参照してくださいするためのテストを書く:

private static readonly Server Server = 
  new Server("localhost");       
TestMethod]
public void CanIConnectToCassandra()
{
  using (var db = new CassandraContext(keyspace: "system", 
    server:Server))
  {
    var version = db.DescribeVersion();
    Assert.IsNotNull(version);
    testContextInstance.WriteLine("Version = {0}", version);
    Assert.AreEqual("19.30.0", version);
  }
}

この記事を読む時に、バージョン番号が私がそれを書いたときから異なることが可能であることに注意してくださいので、2 番目のアサーションが失敗した場合は、チェック、返される文字列を表示するには [出力] ウィンドウ。 (覚えて、調査テスト出力を書く多くの悪い考えでは自動化された単体テストとしてされていないので、API のあなたの理解をテストについてです。)

CassandraContext クラスを実行中のカサンドラ サーバーにそれらのすべてが推測する非常に簡単に接続するための別のオーバー ロードを 5 つがある-彼らはすべて 1 つのフォームまたは別の接続情報の取り扱い。 この特定のケースで私はストアだ (とそれ以降の読み取り) データは、対象のキースペースを作成していないのでカサンドラによって様々 な全身の詳細多くのリレーショナル データベースの最も 1 つのインスタンス データベースのメタデータとセキュリティのために予約であること同じ方法を格納するため、「システム」キースペースへの接続とそのようなです。 しかし、つまり、システム鍵空間を記述する必要はありません。 私は自分自身を作成する次の探査テスト フォームに示すように欲しい図 1

図 1 システム キースペース作成

[TestMethod]
public void DoesMyKeyspaceExistAndCreateItIfItDoesnt()
{
  using (var db = new CassandraContext(keyspace: "system", 
    server:Server))
  {
    bool foundEarth = false;
    foreach (CassandraKeyspace keyspace in db.DescribeKeyspaces())
    {
      Apache.Cassandra.KsDef def = keyspace.GetDescription();
      if (def.Name == "Earth")
        foundEarth = true;
    }
    if (!foundEarth)
    {
      var keyspace = new CassandraKeyspace(new 
      CassandraKeyspaceSchema
      {
        Name = "Earth"
      }, db);
      keyspace.TryCreateSelf();
    }
    Assert.IsTrue(db.KeyspaceExists("Earth"));
  }
}

確かに、データベース内のすべての keyspaces ループが必要です — 私は場所 FluentCassandra は、基になるの中古品ベースの API ピークスと"Apache.Cassandra.KsDef"を入力 API ではそれらの 1 つがあることを示すためにここにそれを行います。

キースは今で、列を少なくとも 1 つの家族、キースペース内を必要とします。 示すようにカサンドラ クエリ言語 (CQL)、漠然と SQL に似た言語では、これを作成する最も簡単な方法を使用して図 2

図 2 カサンドラ クエリ言語を使用して列のファミリを作成します。

[TestMethod]
public void CreateAColumnFamily()
{
  using (var db = new CassandraContext(keyspace: "Earth", 
    server: Server))
  {
    CassandraColumnFamily cf = db.GetColumnFamily("People");
    if (cf == null)
    {
      db.ExecuteNonQuery(@"CREATE COLUMNFAMILY People (
        KEY ascii PRIMARY KEY,
        FirstName text,
        LastName text,
        Age int,
        Title text
);");
    }
    cf = db.GetColumnFamily("People");
    Assert.IsNotNull(cf);
  }
}

CQL の危険性は意図的に SQL のような文法簡単な誤解を組み合わせたその「カサンドラの列が、したがって、それは、リレーショナル データベースのようなテーブルが必要」トリック リレーショナル用語で考えることに不用心な開発者にです。 これは大きく間違っている概念の仮定に します。 たとえば、列にします図 2。 リレーショナル データベースでは、この列の家族の 5 列のみ許可されます。 カサンドラは、単に「ガイドライン」(で、風変わり「カリブの海賊」一種の方法). (CQL をまったく使用しない) に代わる手段が少ない魅力的です:カサンドラ (表示されません) API TryCreateColumnFamily を提供していますが、周りに頭をラップしようと思います。 どのように何回もは、これはまだより不格好と混乱 CQL のアプローチよりも感じています。

' データ、データ、データ ! なしの粘土の煉瓦は作れない ! '

柱ファミリを配置した後は、データベースには、いくつかのオブジェクトをストアとして FluentCassandra API の本当の力で示すように現れる図 3

図 3 データベース内のオブジェクトを保存します。

[TestMethod]
public void StoreSomeData()
{
  using (var db = new CassandraContext(keyspace: "Earth", 
    server: Server))
  {
    var peopleCF = db.GetColumnFamily("People");
    Assert.IsNotNull(peopleCF);
    Assert.IsNull(db.LastError);
    dynamic tedneward = peopleCF.CreateRecord("TedNeward");
    tedneward.FirstName = "Ted";
    tedneward.LastName = "Neward";
    tedneward.Age = 41;
    tedneward.Title = "Architect";
    db.Attach(tedneward);
    db.SaveChanges();
    Assert.IsNull(db.LastError);
  }
}

柱ファミリの名前/値ペアの厳密に型指定されたコレクションではないアイデアを強化する「動的」施設の c# 4.0 の使用に注意してください。 これは c# コードの列指向のデータ ストアの性質を反映するようにできます。 私はので、さらにいくつかのより多くの人々 に示すように格納する場合は、これを見ることができます図 4

図 4 キースペースでより多くの人々 を保存します。

 

[TestMethod]
public void StoreSomeData()
{
  using (var db = new CassandraContext(keyspace: "Earth", 
    server: Server))
  {
    var peopleCF = db.GetColumnFamily("People");
    Assert.IsNotNull(peopleCF);
    Assert.IsNull(db.LastError);
    dynamic tedneward = peopleCF.CreateRecord("TedNeward");
    tedneward.FirstName = "Ted";
    tedneward.LastName = "Neward";
    tedneward.Age = 41;
    tedneward.Title = "Architect";
    dynamic rickgaribay = peopleCF.CreateRecord("RickGaribay");
    rickgaribay.FirstName = "Rick";
    rickgaribay.LastName = "Garibay";
    rickgaribay.HomeTown = "Phoenix";
    dynamic theArtistFormerlyKnownAsPrince =
      peopleCF.CreateRecord("TAFKAP");
    theArtistFormerlyKnownAsPrince.Title = "Rock Star";
    db.Attach(tedneward);
    db.Attach(rickgaribay);
    db.Attach(theArtistFormerlyKnownAsPrince);
    db.SaveChanges();
    Assert.IsNull(db.LastError);
  }
}

再び、ちょうどポイント家を駆動するには、どのようにこの柱ファミリの以前の説明で指定されていない故郷の列はリックに注意してください。 これは、完全に受け入れ、非常に一般的です。

また、FluentCassandra API がデータベースからの最後の例外への参照が含まれている、「LastError」プロパティを提供することに注意してください。 これは、とき、データベースの状態は既に知られていないをチェックすることができます (ようにスローされる例外を食べてかもしれない呼び出しのセットを返すとき、またはデータベースが例外をスローしないに構成されている場合)。

もう一度、気持ちで

データベースへの接続、作成、キースペース (、後でそれをドロップする)、柱ファミリを定義して、シード データの一部を入れて — おそらくこれらのテスト中、多くのこれらのことをするつもり。 そのコードのシーケンスは、事前テストのセットアップに置くし、teardown メソッドをテスト後に偉大な候補です。 キースペース後を切断して、各テストの前に再作成することによって、私はデータベースを自然のまま維持し、既知の状態にするたびに私はテストに示すように実行図 5。 すばらしい。

図 5 は、テストの実行

[TestInitialize]
public void Setup()
{
  using (var db = new CassandraContext(keyspace: "Earth", 
    server: Server))
  {
    var keyspace = new CassandraKeyspace(new CassandraKeyspaceSchema {
      Name = "Earth",
      }, db);
    keyspace.TryCreateSelf();
    db.ExecuteNonQuery(@"CREATE COLUMNFAMILY People (
      KEY ascii PRIMARY KEY,
      FirstName text,
      LastName text,
      Age int,
      Title text);");
    var peopleCF = db.GetColumnFamily("People");
    dynamic tedneward = peopleCF.CreateRecord("TedNeward");
    tedneward.FirstName = "Ted";
    tedneward.LastName = "Neward";
    tedneward.Age = 41;
    tedneward.Title = "Architect";
    dynamic rickgaribay = peopleCF.CreateRecord("RickGaribay");
    rickgaribay.FirstName = "Rick";
    rickgaribay.LastName = "Garibay";
    rickgaribay.HomeTown = "Phoenix";
    dynamic theArtistFormerlyKnownAsPrince =
      peopleCF.CreateRecord("TAFKAP");
    theArtistFormerlyKnownAsPrince.Title = "Rock Star";
    db.Attach(tedneward);
    db.Attach(rickgaribay);
    db.Attach(theArtistFormerlyKnownAsPrince);
    db.SaveChanges();
  }
}
[TestCleanup]
public void TearDown()
{
  var db = new CassandraContext(keyspace: "Earth", server: Server);
  if (db.KeyspaceExists("Earth"))
    db.DropKeyspace("Earth");
}

' 私の作品には、強大なあなたがたを見て、絶望 ! '

カサンドラからデータを読み取り、フォームかかります。 最初に示す CassandraColumnFamily オブジェクトには Get メソッドを使用して列の家族からデータをフェッチすること図 6

図 6 の Get メソッドとデータのフェッチ

[TestMethod]
public void StoreAndFetchSomeData()
{
  using (var db = new CassandraContext(keyspace: "Earth", 
    server: Server))
  {
    var peopleCF = db.GetColumnFamily("People");
    Assert.IsNotNull(peopleCF);
    Assert.IsNull(db.LastError);
    dynamic jessicakerr = peopleCF.CreateRecord("JessicaKerr");
    jessicakerr.FirstName = "Jessica";
    jessicakerr.LastName = "Kerr";
    jessicakerr.Gender = "F";
    db.Attach(jessicakerr);
    db.SaveChanges();
    Assert.IsNull(db.LastError);
    dynamic result = peopleCF.Get("JessicaKerr").FirstOrDefault();
    Assert.AreEqual(jessicakerr.FirstName, result.FirstName);
    Assert.AreEqual(jessicakerr.LastName, result.LastName);
    Assert.AreEqual(jessicakerr.Gender, result.Gender);
  }
}

これは、キー前に時間、しかし、多くの時間を知っている場合はありません素晴らしいです。 実際、それは議論の余地はほとんどの時間は、正確なレコードまたはレコードを知られることはありません。 だから、別のアプローチを (非表示) FluentCassandra の LINQ の統合を使用してスタイルの LINQ クエリを記述します。 これは、しかし伝統的な LINQ として、柔軟ではありません。 列名は、先の時間知られていないため、データベースでは、たとえば (柱ファミリの LastName 名前と値のペアを見る) Newards をすべてを検索する LINQ クエリを記述する多くの困難です。

幸いなことに、CQL の救助に示すように乗り物図 7

図 7 カサンドラの LINQ の統合を使用して LINQ クエリを記述するには

[TestMethod]
public void StoreAndFetchSomeDataADifferentWay()
{
  using (var db = new CassandraContext(keyspace: "Earth", 
    server: Server))
  {
    var peopleCF = db.GetColumnFamily("People");
    Assert.IsNotNull(peopleCF);
    Assert.IsNull(db.LastError);
    dynamic charlotte = peopleCF.CreateRecord("CharlotteNeward");
    charlotte.FirstName = "Charlotte";
    charlotte.LastName = "Neward";
    charlotte.Gender = "F";
    charlotte.Title = "Domestic Engineer";
    charlotte.RealTitle = "Superwife";
    db.Attach(charlotte);
    db.SaveChanges();
    Assert.IsNull(db.LastError);
    var newards =
      db.ExecuteQuery("SELECT * FROM People WHERE LastName='Neward'");
    Assert.IsTrue(newards.Count() > 0);
    foreach (dynamic neward in newards)
    {
      Assert.AreEqual(neward.LastName, "Neward");
    }
  }
}

ただしでは、このコードを実行する場合は、失敗します — カサンドラ手放す文句を言わないインデックスが明示的に定義されている場合を除き、フィルター条件として柱ファミリ内の名前/値ペアを使用します。 そう別の CQL ステートメントが必要です。

db.ExecuteNonQuery(@"CREATE INDEX ON People (LastName)");

通常、セットアップ時に柱ファミリに作成された設定したいと思います。 カサンドラ スキーマより少なくのためにも注意、"を選択 ※"そのクエリの一部は少し不正です — それ列ファミリでは、すべての名前/値ペアが返されますが、それはすべてのレコードのすべての列を持つことを意味しません。 このことを意味し、クエリを"どこ性別 = 'F'"決してリック、テッドと「、アーティスト旧プリンスとして知られて」配慮の葉「ジェンダー」列でそれらを持っていないレコードを検討します。 これは、リレーショナル データベース管理システムから完全に異なる (私はしばしばその責任"NULL"を格納することによってそれらの列にはいくつかの枢機卿の罪になることが考えられているアヒルが) テーブル内のすべての行の各 1 つの列の値が必要です。

完全 CQL 言語はあまりにもここでは、記述するためですが、完全参照カサンドラの Web サイトで利用可能です bit.ly/MHcWr6

今のところをラップ

かなり、呪われた予言者をちょうどまだやったよ — データに取得している間 (は何を彼らはすべての日として) カサンドラの開発者に最も興味深い部分が、マルチノード構成もカサンドラ物語のかなり大きな部分。 1 つの Windows ボックス (開発目的; のためにすること それより簡単に複数のサーバーになるかがわかります) は正確に些細ななぜ、その次の時間をやって議論カサンドラを完結します。

今のところ、幸せなコーディング !

Ted Neward の建築コンサルタントの Neudesic LLC です。 彼は 100 以上の記事を書いたがあり、作成または「プロ F c# 2.0」たくさんの書籍共著 Wrox、2010年).彼は F c# MVP と Java を指摘する専門家と Java と .NET の両方の会議、世界中で話します。彼はコンサルティングを行い、定期的にメンター — 彼に到達 ted@tedneward.com または Ted.Neward@neudesic.com あなたは彼に来てあなたのチームとの仕事に興味を持っている場合。彼はブログで blogs.tedneward.com と Twitter 上で続くことができる Twitter.com/tedneward

この記事のレビュー、次技術専門家のおかげで:ケリー ・ ソマーズ