具有一对多关系的Mongoose文档引用

Jus*_*tin 38 mongoose mongodb node.js mongodb-query mongoose-schema

我正在为一个新项目设计数据库结构,我对MongoDB很新,显然是Mongoose.

我已经阅读过Mongooses 人口文档,它有一对多的关系,一个Person文档到很多Story文档,但是令我困惑的部分是在哪里而不是Story引用Person它所属的文档的文档,Person架构设置了它所以它有一个Story"拥有"的文件数组.

我正在设置与此类似的东西.但我一直认为创建新Story文档以获取Person文档ID 会更容易.但也许这只是因为我更熟悉使用连接的MySQL关系.

如果这是最好的方法(并且我确定它是,因为它在文档中),在Story创建新文档时,最新的方法是更新People它所属的相关文档中的故事数组?我看了但找不到任何更新现有文档的例子来添加对其他文件的引用(或删除它们)

我确信这是一个简单的解决方案,我只是忽略了什么,但任何帮助都会很棒.谢谢!

Kei*_*Tai 43

参考人口,这里从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);
Run Code Online (Sandbox Code Playgroud)

所以有关,示例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);
});
Run Code Online (Sandbox Code Playgroud)

我相信这就是你要找的.或者,您可以使用嵌套集合.

  • 好的,所以`Story._creator`会自动引用父`Person._id`吗?或者您是否必须分别更新`Story._creator`和`Person.stories`值?我真正更关心的是,当你创建一个新故事时......更新父母`故事`数组的最佳方法是什么?有没有办法通过单个查询将新Id推送到它?或者你必须查询整个文档,然后将新故事推送到`Person.stories`数组,然后更新`Person`文档? (3认同)
  • 这让我担心它们是否可能不同步,如果我有其他脚本正在使用该数据库,或者有人手动将其弄乱了。 (3认同)

Man*_*iel 7

正如在人口文件中说的那样

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);
});
Run Code Online (Sandbox Code Playgroud)

  • 如果删除了`story1`,那么它是否需要一个`aaron.stories.pop(story1)`? (2认同)

Col*_*ent 5

先前对该问题的回答很有帮助,但查看更详细的代码可能会很有用。以下代码来自于我的应用程序的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;
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

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 lines 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 });
      });
};
Run Code Online (Sandbox Code Playgroud)

user_controller.js

 export const createUser = (req, res) => {
   const user = new User();
   user.username = req.body.username;
   user.email = req.body.email;
   user.save()
       .then((result) => {
            res.json({ message: 'User created!', result });
        })
        .catch((error) => {
          res.status(500).json({ error });
        });
    };

// . . .
// 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 });
      });
  };
Run Code Online (Sandbox Code Playgroud)

  • 这么好的解释!谢谢 (2认同)