web-dev-qa-db-ja.com

mongoの外部キー?

enter image description here

MongoDBでこのようなスキームを設計するにはどうすればよいですか?外部キーはないと思います!

78
Mark Pegasov

MongoidやMongoMapperなどのORMの使用に興味があるかもしれません。

http://mongoid.org/docs/relations/referenced/1-n.html

MongoDBのようなNoSQLデータベースには、「テーブル」ではなくドキュメントがあります。ドキュメントはコレクション内にグループ化されます。単一のコレクションに、あらゆる種類のドキュメント、あらゆる種類のデータを含めることができます。基本的に、NoSQLデータベースでは、データとその関係があれば、それを整理する方法を決定するのはユーザー次第です。

MongoidとMongoMapperが行うことは、リレーションを非常に簡単に設定するための便利な方法を提供することです。私があなたに与えたリンクをチェックして、何かを尋ねてください。

編集:

Mongoidでは、次のようにスキームを記述します。

class Student
  include Mongoid::Document

    field :name
    embeds_many :addresses
    embeds_many :scores    
end

class Address
  include Mongoid::Document

    field :address
    field :city
    field :state
    field :postalCode
    embedded_in :student
end

class Score
  include Mongoid::Document

    belongs_to :course
    field :grade, type: Float
    embedded_in :student
end


class Course
  include Mongoid::Document

  field :name
  has_many :scores  
end

編集:

> db.foo.insert({group:"phones"})
> db.foo.find()                  
{ "_id" : ObjectId("4df6539ae90592692ccc9940"), "group" : "phones" }
{ "_id" : ObjectId("4df6540fe90592692ccc9941"), "group" : "phones" }
>db.foo.find({'_id':ObjectId("4df6539ae90592692ccc9940")}) 
{ "_id" : ObjectId("4df6539ae90592692ccc9940"), "group" : "phones" }

そのObjectIdを使用して、ドキュメント間の関係を作成できます。

23
Nerian

Mongodbでこのようにテーブルを設計する方法は?

まず、いくつかの命名規則を明確にします。 MongoDBは、collectionsの代わりにtablesを使用します。

外部キーはないと思います!

次のモデルを使用します。

student
{ 
  _id: ObjectId(...),
  name: 'Jane',
  courses: [
    { course: 'bio101', mark: 85 },
    { course: 'chem101', mark: 89 }
  ]
}

course
{
  _id: 'bio101',
  name: 'Biology 101',
  description: 'Introduction to biology'
}

明らかに、ジェーンのコースリストはいくつかの特定のコースを指しています。データベースはシステムに制約を適用しません()。つまり、外部キー制約)。したがって、「カスケード削除」または「カスケード更新」はありません。ただし、データベースには正しい情報が含まれています。

さらに、MongoDBには DBRef標準 があり、これらの参照の作成を標準化するのに役立ちます。実際、そのリンクを見ると、同様の例があります。

このタスクを解決するにはどうすればよいですか?

明確にするために、MongoDBはリレーショナルではありません。標準の「標準形式」はありません。保存するデータと実行するクエリに適したデータベースをモデル化する必要があります。

59
Gates VP

From The Little MongoDB Book

結合を使用するもう1つの方法は、データの非正規化です。歴史的に、非正規化は、パフォーマンスに敏感なコード、またはデータをスナップショットする必要がある場合(監査ログなど)に予約されていました。ただし、NoSQLの人気が高まり、その多くに結合が含まれていないため、通常のモデリングの一部としての非正規化がますます一般的になっています。これは、すべてのドキュメントのすべての情報を複製する必要があるという意味ではありません。ただし、データの重複を恐れて設計上の決定を下すのではなく、どの情報がどのドキュメントに属するかに基づいてデータをモデリングすることを検討してください。

そう、

student
{ 
    _id: ObjectId(...),
    name: 'Jane',
    courses: [
    { 
        name: 'Biology 101', 
        mark: 85, 
        id:bio101 
    },
  ]
}

RESTful APIデータの場合、コースIDをコースリソースへのGETリンクに置き換えます

15
ZAky

MongoDBでforeign keyと呼ばれるものを定義できます。ただし、データの整合性を維持する必要がありますBY OURSELVES。例えば、

student
{ 
  _id: ObjectId(...),
  name: 'Jane',
  courses: ['bio101', 'bio102']   // <= ids of the courses
}

course
{
  _id: 'bio101',
  name: 'Biology 101',
  description: 'Introduction to biology'
}

coursesフィールドには、_idsのコースが含まれます。 1対多の関係を定義するのは簡単です。ただし、学生Janeのコース名を取得する場合は、_idを介してcourseドキュメントを取得する別の操作を実行する必要があります。

コースbio101が削除された場合、coursesドキュメントのstudentフィールドを更新する別の操作を実行する必要があります。

詳細:MongoDBスキーマデザイン

MongoDBのドキュメントタイプの性質は、関係を定義する柔軟な方法をサポートします。 1対多の関係を定義するには:

埋め込み文書

  1. 1対2に適しています。
  2. 利点:別のドキュメントに対して追加のクエリを実行する必要がありません。
  3. 欠点:埋め込みドキュメントのエンティティを個別に管理することはできません。

例:

student
{
  name: 'Kate Monster',
  addresses : [
     { street: '123 Sesame St', city: 'Anytown', cc: 'USA' },
     { street: '123 Avenue Q', city: 'New York', cc: 'USA' }
  ]
}

子参照

上記のstudent/courseの例のように。

親参照

ログメッセージなど、1対10に適しています。

Host
{
    _id : ObjectID('AAAB'),
    name : 'goofy.example.com',
    ipaddr : '127.66.66.66'
}

logmsg
{
    time : ISODate("2014-03-28T09:42:41.382Z"),
    message : 'cpu is on fire!',
    Host: ObjectID('AAAB')       // Reference to the Host document
}

実質的に、Hostlogmsgの親です。 Host idを参照すると、ログメッセージが大量にあるため、スペースを大幅に節約できます。

参照:

  1. MongoDBスキーマ設計の経験則:パート1
  2. MongoDBスキーマ設計の6つの経験則:パート2
  3. MongoDBスキーマ設計の6つの経験則:パート
  4. ドキュメント参照とのモデル一対多関係
13
Joy