Подтвердить что ты не робот

Ссылки на документ Mongoose с отношением "один ко многим"

Я работаю над созданием структуры базы данных для нового проекта, и я довольно новичок в MongoDB и, очевидно, Mongoose.

Я читал документацию Mongooses , где она имеет отношение "один ко многим", причем один документ Person для многих Story, но часть, которая меня смущает, заключается в том, где вместо документов Story, ссылающихся на документ Person, к которому он принадлежит, схема Person имеет его настройку, поэтому у него есть массив того, что Story владеет.

Я настраиваю что-то очень похожее на это. Но я считаю, что при создании новых документов Story было бы легче иметь идентификатор документа Person. Но, возможно, это потому, что я больше знаком с отношениями MySQL с использованием объединений.

Если это лучший способ сделать это (и я уверен, что это, так как в документах), когда создаются новые документы Story, что лучший способ обновить массив рассказов в связанных People Документ, к которому он принадлежит? Я посмотрел, но не смог найти примеров обновления существующих документов, чтобы добавить ссылки на другие документы (или удалить их, если на то пошло)

Я уверен, что это простое решение, которое я просто забыл или что-то в этом роде, но любая помощь была бы замечательной. Спасибо!

4b9b3361

Ответ 1

Обратитесь к населению, здесь извлеките пример из мангуста.

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

Я считаю, что это то, что вы ищете. Или же вы можете использовать вместо этого вложенные коллекции.

Ответ 2

Как сказано в документации для населения

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

Ответ 3

Предыдущие ответы на этот вопрос были полезны, но может быть полезно увидеть более подробный код. Приведенный ниже код взят из моего бэкэнда 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 
                // ObjectID to the the User 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({ path: 'reviews' })
      .then((result) => {
        res.json(result);
      })
      .catch((error) => {
        res.status(500).json({ error });
      });
  };