web-dev-qa-db-fra.com

Références de documents Mongoose avec une relation un à plusieurs

Je travaille sur la conception d'une structure de base de données pour un nouveau projet, et je suis plutôt nouveau dans MongoDB, et évidemment dans Mongoose.

J'ai lu Mongooses population documentation, où il existe une relation un-à-plusieurs, avec un Person document à plusieurs Story documents, mais la partie qui confond me est où, au lieu des documents Story référençant le document Person auquel il appartient, le schéma Person a été configuré de sorte qu'il contienne un tableau de ce que Story les documents qu'il "possède".

Je suis en train de mettre en place quelque chose de très similaire à cela. Mais je continue de penser que ce serait plus facile lors de la création de nouveaux documents Story d’avoir l’ID de document Person. Mais c’est peut-être parce que je suis plus familier avec les relations MySQL qui utilisent des jointures.

Si c’est le meilleur moyen de le faire (et je suis sûr que c’est le cas, étant donné que cela se trouve dans la documentation), lors de la création de nouveaux documents Story, quel est le meilleur moyen de mettre à jour le tableau des récits dans les fichiers associés. People document auquel il appartient? J'ai cherché mais je n'ai trouvé aucun exemple de mise à jour de documents existants afin d'ajouter des références à d'autres documents (ou de les supprimer d'ailleurs).

Je suis sûr que c'est une solution facile que je viens de négliger ou quelque chose du genre, mais toute aide serait formidable. Merci!

33
Justin

Reportez-vous à population , extrait ici un exemple de 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);

Ainsi, l'exemple à propos de Story modèle stocke les objets liés Person._id Dans Story._creator. Lorsque vous trouvez un document de Story, vous pouvez utiliser la méthode populate() pour définir quel attribut dans le modèle Person vous souhaitez récupérer en même temps, par exemple:

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

Je crois que c'est ce que vous cherchez. Sinon, vous pouvez utiliser collections imbriquées .

41
Keiran Tai

Comme dans population docs dit

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

Les réponses précédentes à cette question étaient utiles, mais il serait peut-être utile de voir un code plus détaillé. Le code ci-dessous provient de mon backend Express.js pour mon application. Mon application permet aux utilisateurs d'écrire des critiques. En interrogeant l'utilisateur, je renvoie toutes les critiques que l'utilisateur a faites.

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