2016-04-04 10 views
0

私はいくつかのレビューのためのコレクションを設計しました。
レビューコレクションスキーマには投稿とトピックの両方が含まれています。
投稿のプロパティ(key、phone、date、contents、author.name)はレビューコレクションの直接の子です。
トピックプロパティ(キー、タイトル)は、レビューコレクションの子であるトピックオブジェクトの子です。
各投稿はトピックに属します。
各投稿キーは一意で、各トピックキーは一意です。 ?正しいトピックのプロパティを複製するという決定がある、または私は別の使用する必要があります。多くの記事が話題に属している場合
は、トピックのデータは、(NoSQLのは右、ACIDではありません:-)マングース:文書の重複を避けるにはどうすればいいですか?

質問がされ、各レビューのために繰り返されます投稿とトピックのコレクション?

これは私のモデルである:

var reviewSchema = new mongoose.Schema({ 
    key: String, 
    phone: String, 
    date: Date, 
    contents: String, 
    author: { 
    name: String, 
    }, 
    topic: { 
    key: String, 
    title: String, 
    }, 
}); 
reviewSchema.index({ 'key': 1 }, { unique: true }); 
reviewSchema.index({ 'phone': 1 }, { unique: false }); 
reviewSchema.index({ 'topic.key': 1 }, { unique: false }); 

答えて

4

あなたは、あなたのReview秒でそれを参照し、Topic用に別のスキーマを作成し、重複を避けたい場合は、次の

var TopicSchema = new mongoose.Schema({ 
    key: String, 
    title: String 
}); 

var ReviewSchema = new mongoose.Schema({ 
    key: String, 
    phone: String, 
    ... 
    topic: {type: Schema.Types.ObjectId, ref: 'Topic'} 
}); 

var Topic = mongoose.model('Topic', TopicSchema); 
var Review = mongoose.model('Review', ReviewSchema); 

ここから、使用Topicをサブ文書として使用してReviewを挿入する場合はpopulate()methodです。自分自身の文書にauthorを格納しているという事実に基づいて、そこに同じパターンをたどることを検討することができます。

私はkeyの使用について不思議です。 MongoDBは、一義的な一種のキーであるトップレベルのドキュメントにユニークな_idをデフォルトで作成します。それがkeyのあなたの意図なら、おそらくMongoDBがそれを処理させるべきです。

しかし、一日の終わりには、問題に対する「正しい」解決法はなく、トレードオフの比較のみです。 MongoDBのメリットは、簡単に「質問するものを保存する」機能です。Topicは非常に小さいので、レビューを取得するたびにトピックが必要な場合は、重複する価値があります。 MongoDBはコレクション内のACIDではありません(他のNoSQLオプションでは話すことができません)。この方法では、すべての埋め込みトピックを一度に更新すると、ユーザーに短時間の不一致が生じる可能性があります。

// Get entire review in one go, including subdocuments! 
Review.findOne({ "key": "myReview" }, (err, doc) => { /* do things */ }); 

// On bulk topic updates, not all topics change at once (not ACIDic) 
Review.update(
    { topic.title: 'foo' }, 
    { topic.title: 'bar' }, 
    { multi: true }, 
    (err, doc) => {/* callback */ } 
); 

あなたはSQLの背景から来ている場合は、上記のpopulate()パラダイムは、はるかに快適になります。また、MongoDBはドキュメントごとにACIDicなので、トピックを一度更新すれば、それを参照する他のすべてのドキュメントで十分です。その背景には、Mongooseが少なくとも2つのクエリを作成する必要があります:Reviewの場合は1回、次にTopicの場合はもう一度クエリを実行します。私の経験で

// To replace refs with documents two queries behind the scenes 
Review.findOne({ key: 'myReview' }) 
    .populate('topic').exec((err, review) => { /* do things */ }) 

// But updating a single topic is ACIDic, since reviews only contain references 
Topic.update({ key: 'foo' }, { title: 'sci-fi' }, (err, res) => {/* more stuff */ }) 

あなたが制限するためにあなたのクエリパイプラインを押し、すべてのコストで、応答時間を削減したいしている場合を除き、populate()との別個のスキーマは、余分なクエリのトレードオフの価値があります。

+0

ありがとうございます!この種のデータの複製が受け入れられることを確認することが重要でした。:-) – MarcoS

+0

絶対に!参考になった場合は回答を受け入れてください。 – ggallo

+0

より完全な答えを得るために数日待つだけです... :-) – MarcoS

関連する問題