84 votes

Comment définir ObjectId comme type de données dans Mongoose ?

J'utilise node.js, mongodb sur mongoHQ et mongoose. Je suis en train de définir un schéma pour les catégories. Je voudrais utiliser l'ObjectId du document comme categoryId.

var mongoose = require('mongoose');

var Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;
var Schema_Category = new Schema({
    categoryId  : ObjectId,
    title       : String,
    sortIndex   : String
});

Je lance ensuite

var Category = mongoose.model('Schema_Category');
var category = new Category();
category.title = "Bicycles";
category.sortIndex = "3";

category.save(function(err) {
  if (err) { throw err; }
  console.log('saved');
  mongoose.disconnect();     
});

Remarquez que je ne fournis pas de valeur pour categoryId. J'ai supposé que la mangouste utiliserait le schéma pour le générer, mais le document contient l'habituel "_id" et non "categoryId". Qu'est-ce que je fais de mal ?

137voto

addisonj Points 970

Contrairement aux RBDM traditionnels, mongoDB ne vous permet pas de définir n'importe quel champ aléatoire comme clé primaire, le champ _id DOIT exister pour tous les documents standard.

Pour cette raison, il n'est pas utile de créer un champ uuid distinct.

Dans Mongoose, le type ObjectId n'est pas utilisé pour créer un nouvel uuid, mais plutôt pour référencer d'autres documents.

Voici un exemple :

var mongoose = require('mongoose');

var Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;
var Schema_Product = new Schema({
    categoryId  : ObjectId, // a product references a category _id with type ObjectId
    title       : String,
    price       : Number
});

Comme vous pouvez le voir, cela n'aurait pas beaucoup de sens de remplir categoryId avec un ObjectId.

Cependant, si vous voulez un champ uuid bien nommé, la mangouste fournit des propriétés virtuelles qui vous permettent de faire référence à un champ.

Regardez ça :

var mongoose = require('mongoose');

var Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;
var Schema_Category = new Schema({
    title       : String,
    sortIndex   : String
});

Schema_Category.virtual('categoryId').get(function() {
    return this._id;
});

Donc maintenant, chaque fois que vous appelez category.categoryId, la mangouste renvoie simplement l'_id à la place.

Vous pouvez également créer une méthode "set" pour définir des propriétés virtuelles. ce lien pour plus d'informations

0 votes

Après avoir défini une propriété virtuelle, j'ai essayé : db.cats.find({categoryId : ObjectId("the id")}) mais j'ai obtenu des résultats nuls. Lorsque j'utilise db.cats.find({_id : ObjectId("the id")}), j'ai obtenu un document en retour. Il semble donc que la propriété virtuelle ne puisse pas être utilisée pour la recherche. Je pense qu'il serait plus facile de gérer le code s'il était possible de référencer chaque ID en utilisant un nom clair, plutôt que d'utiliser _id pour tout. C'est juste une idée...

58voto

jpenna Points 690

Je cherchais une réponse différente pour le titre de la question, alors peut-être que d'autres personnes le feront aussi.

Pour définir le type comme un ObjectId (afin que vous puissiez faire référence à author comme l'auteur de book par exemple), vous pouvez faire comme suit :

const Book = mongoose.model('Book', {
  author: {
    type: mongoose.Schema.Types.ObjectId, // here you set the author ID
                                          // from the Author colection, 
                                          // so you can reference it
    required: true
  },
  title: {
    type: String,
    required: true
  }
});

5voto

dbx Points 41

Ma solution pour utiliser ObjectId

// usermodel.js

const mongoose = require('mongoose')
const Schema = mongoose.Schema
const ObjectId = Schema.Types.ObjectId

let UserSchema = new Schema({
   username: {
     type: String
   },
   events: [{
     type: ObjectId,
     ref: 'Event' // Reference to some EventSchema
   }]
})

UserSchema.set('autoIndex', true)

module.exports = mongoose.model('User', UserSchema)

En utilisant la méthode de la mangouste remplir méthode

// controller.js

const mongoose = require('mongoose')
const User = require('./usermodel.js')

let query = User.findOne({ name: "Person" })

query.exec((err, user) => {
  if (err) {
     console.log(err)
  }

  user.events = events
  // user.events is now an array of events
})

2voto

La solution fournie par @dex a fonctionné pour moi. Mais je veux ajouter quelque chose d'autre qui a également fonctionné pour moi : Utilisez

let UserSchema = new Schema({
   username: {
     type: String
   },
   events: [{
     type: ObjectId,
     ref: 'Event' // Reference to some EventSchema
   }]
})

si ce que vous voulez créer est une référence à un tableau. Mais si ce que vous voulez est une référence à un objet, ce qui est ce que vous recherchez de toute façon, enlevez les parenthèses de la balise valeur prop, comme ça :

let UserSchema = new Schema({
   username: {
     type: String
   },
   events: {
     type: ObjectId,
     ref: 'Event' // Reference to some EventSchema
   }
})

Regardez bien les 2 extraits. Dans le deuxième cas, la value prop des key events n'a pas de parenthèses sur l'object def.

1voto

Kishan Chauhan Points 1

Vous pouvez définir directement l'ObjectId

var Schema = new mongoose.Schema({ categoryId : mongoose.Schema.Types.ObjectId, title : String, sortIndex : String })

Note : Vous devez importer le module mongoose

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