web-dev-qa-db-ja.com

1対多の関係を持つMongooseドキュメント参照

私は新しいプロジェクトのデータベース構造の設計に取り組んでおり、MongoDB、そして明らかにMongooseにはかなり新しいです。

Mongooses population documentationを読みました。1対多の関係があり、1つのPersonドキュメントと多くのStoryドキュメントがありますが、混乱するのは、Storyドキュメントではなく、それが属するPersonドキュメント、Personスキーマはセットアップされているため、Storyドキュメントが「所有」しているものの配列を持っています。

これと非常によく似たものを設定しています。しかし、新しいStoryドキュメントを作成すると、PersonドキュメントIDを持つ方が簡単だと考え続けています。しかし、それはおそらく、結合を使用したMySQLの関係に精通しているからです。

これがそれを行うための最良の方法である場合(そしてドキュメントにあるので、私はそれがあると確信しています)、新しいStoryドキュメントが作成されるとき、それが属する関連するPeopleドキュメント内のストーリーの配列を更新する最良の方法は何ですか?探しましたが、既存のドキュメントを更新して他のドキュメントへの参照を追加する(または削除する)例は見つかりませんでした

これは私が見落としていた簡単な解決策か何かだと確信していますが、どんな助けも素晴らしいでしょう。ありがとう!

33
Justin

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._idStory._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);
});

これがあなたが探しているものだと思います。または、代わりに ネストされたコレクション を使用できます。

41
Keiran Tai

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);
});
7
Manasov Daniel

この質問に対する以前の回答は役に立ちましたが、より詳細なコードを見ると役立つ場合があります。以下のコードは、アプリケーションの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 });
      });
  };
1
College Student