151 votes

Référencement d'un autre schéma dans Mongoose

Si j'ai deux schémas comme :

var userSchema = new Schema({
    twittername: String,
    twitterID: Number,
    displayName: String,
    profilePic: String,
});

var  User = mongoose.model('User') 

var postSchema = new Schema({
    name: String,
    postedBy: User,  //User Model Type
    dateCreated: Date,
    comments: [{body:"string", by: mongoose.Schema.Types.ObjectId}],
});

J'ai essayé de les connecter ensemble comme dans l'exemple ci-dessus, mais je n'ai pas réussi à trouver comment le faire. Finalement, si je peux faire quelque chose comme ça, ça me faciliterait la vie.

var profilePic = Post.postedBy.profilePic

259voto

nicksweet Points 637

Il semble que la méthode populate soit ce que vous recherchez. Tout d'abord, modifiez légèrement le schéma de vos messages :

var postSchema = new Schema({
    name: String,
    postedBy: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
    dateCreated: Date,
    comments: [{body:"string", by: mongoose.Schema.Types.ObjectId}],
});

Ensuite, faites votre modèle :

var Post = mongoose.model('Post', postSchema);

Ensuite, lorsque vous faites votre requête, vous pouvez remplir les références comme ceci :

Post.findOne({_id: 123})
.populate('postedBy')
.exec(function(err, post) {
    // do stuff with post
});

30voto

fino Points 948

Addendum : Personne n'a mentionné "Populate" --- cela vaut vraiment la peine de consacrer du temps et de l'argent à la méthode Populate de Mongooses : elle explique également le référencement des documents croisés.

http://mongoosejs.com/docs/populate.html

17voto

D. Lowe Points 133

Réponse tardive, mais ajouter que Mongoose a également le concept de Sous-documents

Avec cette syntaxe, vous devriez être en mesure de faire référence à votre userSchema comme un type dans votre postSchema comme ça :

var userSchema = new Schema({
    twittername: String,
    twitterID: Number,
    displayName: String,
    profilePic: String,
});

var postSchema = new Schema({
    name: String,
    postedBy: userSchema,
    dateCreated: Date,
    comments: [{body:"string", by: mongoose.Schema.Types.ObjectId}],
});

Notez la mise à jour postedBy champ de type userSchema .

Cela permet d'intégrer l'objet utilisateur dans le message, ce qui évite la recherche supplémentaire requise par l'utilisation d'une référence. Parfois, cela peut être préférable, mais dans d'autres cas, la route ref/populate peut s'avérer plus appropriée. Tout dépend de ce que fait votre application.

2voto

Display name Points 51

Ceci s'ajoute à la réponse de D. Lowe qui a fonctionné pour moi mais qui a nécessité quelques ajustements. (J'aurais bien mis cela en commentaire mais je n'ai pas la réputation de le faire, et j'aimerais retrouver cette information dans quelques mois lorsque je rencontrerai à nouveau ce problème mais que j'aurai oublié comment le résoudre).

Si vous importez un schéma à partir d'un autre fichier, vous devrez ajouter .schema à la fin de l'importation.

Note : Je ne sais pas si vous obtenez la configuration de schéma invalide si vous n'importez pas de schémas et utilisez des schémas locaux à la place, mais l'importation est simplement plus propre et plus facile à gérer pour moi.

Par exemple :

// ./models/other.js
const mongoose = require('mongoose')

const otherSchema = new mongoose.Schema({
    content:String,
})

module.exports = mongoose.model('Other', otherSchema)

//*******************SEPERATE FILES*************************//

// ./models/master.js
const mongoose = require('mongoose')

//You will get the error "Invalid schema configuration: `model` is not a valid type" if you omit .schema at the end of the import
const Other=require('./other').schema

const masterSchema = new mongoose.Schema({
    others:[Other],
    singleOther:Other,
    otherInObjectArray:[{
        count:Number,
        other:Other,
    }],
})

module.exports = mongoose.model('Master', masterSchema);

Ensuite, quel que soit l'endroit où vous l'utilisez (pour moi, j'ai utilisé un code similaire à celui-ci dans mon API Node.js), vous pouvez simplement assigner l'autre au maître.

Par exemple :

const Master= require('../models/master')
const Other=require('../models/other')

router.get('/generate-new-master', async (req, res)=>{
    //load all others
    const others=await Other.find()

    //generate a new master from your others
    const master=new Master({
        others,
        singleOther:others[0],
        otherInObjectArray:[
            {
                count:1,
                other:others[1],
            },
            {
                count:5,
                other:others[5],            
            },
        ],
    })

    await master.save()
    res.json(master)
})

1voto

Spadefaith Points 51
{body: "string", by: mongoose.Schema.Types.ObjectId}

Le site mongoose.Schema.Types.ObjectId créera un nouvel identifiant, essayez de le changer pour un type plus direct, comme String ou Number.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X