MongoDBでこのようなスキームを設計するにはどうすればよいですか?外部キーはないと思います!
MongoDBでこのようなスキームを設計するにはどうすればよいですか?外部キーはないと思います!
回答:
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を使用できます。
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はリレーショナルではありません。標準の「通常の形式」はありません。格納するデータと実行するクエリに適したデータベースをモデル化する必要があります。
いわゆるforeign key
MongoDBで定義できます。しかし、我々は、データの整合性を維持する必要が自分で。例えば、
student
{
_id: ObjectId(...),
name: 'Jane',
courses: ['bio101', 'bio102'] // <= ids of the courses
}
course
{
_id: 'bio101',
name: 'Biology 101',
description: 'Introduction to biology'
}
courses
フィールドが含まれている_id
コースの秒。1対多の関係を定義するのは簡単です。ただし、studentのコース名を取得する場合は、Jane
別の操作を実行してをcourse
介してドキュメントを取得する必要があります_id
。
コースbio101
が削除された場合、ドキュメントのcourses
フィールドを更新するために別の操作を実行する必要がありstudent
ます。
MongoDBのドキュメントタイプの性質は、関係を定義する柔軟な方法をサポートします。1対多の関係を定義するには:
例:
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〜数十億に適しています。
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
}
事実上、aはのhost
親ですlogmsg
。host
ログメッセージが数十億である場合、IDを参照すると多くのスペースを節約できます。
参照:
結合を使用するもう1つの方法は、データを非正規化することです。歴史的に、非正規化はパフォーマンスに敏感なコードのために、またはデータを(監査ログのように)スナップショットする必要があるときに予約されていました。ただし、NoSQLの人気が高まり、その多くに結合がないため、通常のモデリングの一部としての非正規化がますます一般的になっています。これは、すべてのドキュメントのすべての情報を複製する必要があるという意味ではありません。ただし、データの重複を恐れて設計上の決定を下すのではなく、どの情報がどのドキュメントに属しているかに基づいてデータをモデル化することを検討してください。
そう、
student
{
_id: ObjectId(...),
name: 'Jane',
courses: [
{
name: 'Biology 101',
mark: 85,
id:bio101
},
]
}
RESTful APIデータの場合、コースIDをコースリソースへのGETリンクに置き換えます
ForeignKeyの目的は、フィールド値がそのForeignKeyと一致しない場合にデータの作成を防ぐことです。MongoDBでこれを実現するために、データの一貫性を保証するスキーマミドルウェアを使用します。
ドキュメントをご覧ください。 https://mongoosejs.com/docs/middleware.html#pre