私は新しいプロジェクトのデータベース構造の設計に取り組んでおり、MongoDB、そして明らかにMongooseにはかなり新しいです。
Mongooses population documentationを読みました。1対多の関係があり、1つのPerson
ドキュメントと多くのStory
ドキュメントがありますが、混乱するのは、Story
ドキュメントではなく、それが属するPerson
ドキュメント、Person
スキーマはセットアップされているため、Story
ドキュメントが「所有」しているものの配列を持っています。
これと非常によく似たものを設定しています。しかし、新しいStory
ドキュメントを作成すると、Person
ドキュメントIDを持つ方が簡単だと考え続けています。しかし、それはおそらく、結合を使用したMySQLの関係に精通しているからです。
これがそれを行うための最良の方法である場合(そしてドキュメントにあるので、私はそれがあると確信しています)、新しいStory
ドキュメントが作成されるとき、それが属する関連するPeople
ドキュメント内のストーリーの配列を更新する最良の方法は何ですか?探しましたが、既存のドキュメントを更新して他のドキュメントへの参照を追加する(または削除する)例は見つかりませんでした
これは私が見落としていた簡単な解決策か何かだと確信していますが、どんな助けも素晴らしいでしょう。ありがとう!
population を参照してください。ここではMongooseから例を抽出します。
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var personSchema = Schema({
_id : Schema.Types.ObjectId,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
_creator : { type: Schema.Types.ObjectId, ref: 'Person' },
title : String,
fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
そのため、Story
モデルに関する例は、関連するPerson._id
をStory._creator
に格納します。 Story
のドキュメントが見つかったら、populate()
メソッドを使用して、Person
モデルのどの属性を同時に取得するかを定義できます。
Story.findOne({_id: 'xxxxxxx'}).populate('person', 'name age').exec(function(err, story) {
console.log('Story title: ', story.title);
console.log('Story creator', story.person.name);
});
これがあなたが探しているものだと思います。または、代わりに ネストされたコレクション を使用できます。
population docs のように
var aaron = new Person({ _id: 0, name: 'Aaron', age: 100 });
aaron.save(function (err) {
if (err) return handleError(err);
var story1 = new Story({
title: "Once upon a timex.",
_creator: aaron._id // assign the _id from the person
});
story1.save(function (err) {
if (err) return handleError(err);
// thats it!
});
//then add story to person
aaron.stories.Push(story1);
aaron.save(callback);
});
この質問に対する以前の回答は役に立ちましたが、より詳細なコードを見ると役立つ場合があります。以下のコードは、アプリケーションのExpress.jsバックエンドからのものです。私のアプリケーションでは、ユーザーがレビューを書くことができます。ユーザーに照会すると、ユーザーが行ったすべてのレビューを返します。
user_model.js
import mongoose, { Schema } from 'mongoose';
const UserSchema = new Schema({
firstname: String,
lastname: String,
username: { type: String, unique: true },
reviews: [{ type: Schema.Types.ObjectId, ref: 'Review' }],
}, {
toJSON: {
virtuals: true,
},
});
const UserModel = mongoose.model('User', UserSchema);
export default UserModel;
review_model.js
import mongoose, { Schema } from 'mongoose';
const ReviewSchema = new Schema({
body: String,
username: String,
rating: Number,
}, {
toJSON: {
virtuals: true,
},
});
const ReviewModel = mongoose.model('Review', ReviewSchema);
export default ReviewModel;
review_controller.js
// . . .
export const createReview = (req, res) => {
const review = new Review();
review.username = req.body.username;
review.rating = req.body.rating;
review.body = req.body.body;
review.save()
.then((result) => {
User.findOne({ username: review.username }, (err, user) => {
if (user) {
// The below two line will add the newly saved review's
// ObjectID to the the User's reviews array field
user.reviews.Push(review);
user.save();
res.json({ message: 'Review created!' });
}
});
})
.catch((error) => {
res.status(500).json({ error });
});
};
user_controller.js
// . . .
// returns the user object associated with the username if any
// with the reviews field containing an array of review objects
// consisting of the reviews created by the user
export const getUser = (req, res) => {
User.findOne({ username: req.params.username })
.populate('reviews')
.then((result) => {
res.json(result);
})
.catch((error) => {
res.status(500).json({ error });
});
};