web-dev-qa-db-fra.com

Quel est le type correct à utiliser pour un champ ObjectId sur Mangoose et GraphQL?

Après ce tutoriel , j'ai un modèle de mangouste: (J'utilise le terme "Compte" au lieu de "Todo", mais c'est la même chose)

const Account = mongoose.model('Account', new mongoose.Schema({
  id: mongoose.Schema.Types.ObjectId,
  name: String
}));

et un GraphQLObjectType:

const AccountType = new GraphQLObjectType({
  name: 'account',
  fields: function () {
    return {
      id: {
        type: GraphQLID
      },
      name: {
        type: GraphQLString
      }
    }
  }
});

et une mutation GraphQL pour en créer un:

const mutationCreateType = new GraphQLObjectType({
  name: 'Mutation',
  fields: {
    add: {
      type: AccountType,
      description: 'Create new account',
      args: {
        name: {
          name: 'Account Name',
          type: new GraphQLNonNull(GraphQLString)
        }
      },
      resolve: (root, args) => {
        const newAccount = new Account({
          name: args.name
        });

        newAccount.id = newAccount._id;

        return new Promise((resolve, reject) => {
          newAccount.save(err => {
            if (err) reject(err);
            else resolve(newAccount);
          });
        });
      }
    }
  }
})

Après avoir exécuté la requête:

mutation {
  add(name: "Potato")
  {
    id,
    name
  }
}

dans GraphiQL, je reçois la réponse:

{
  "errors": [
    {
      "message": "ID cannot represent value: { _bsontype: \"ObjectID\", id: <Buffer 5b 94 eb ca e7 4f 2d 06 43 a6 92 20> }",
      "locations": [
        {
          "line": 33,
          "column": 5
        }
      ],
      "path": [
        "add",
        "id"
      ]
    }
  ],
  "data": {
    "add": {
      "id": null,
      "name": "Potato"
    }
  }
}

La création de l'objet a réussi et je peux le voir dans MongoDB Compass:

 From MongoDB Compass showing created object

mais il semble y avoir un problème de lecture de la valeur.

Dans quelle mesure GraphQLID et mongoose.Schema.Types.ObjectId sont-ils compatibles? S'ils ne sont pas compatibles, je ne comprends pas le didacticiel, en particulier l'utilisation de:

newAccount.id = newAccount._id;

? Je ne peux pas dire si l'erreur provient de GraphQL, de MongoDB, de Mongoose ou de quelque chose d'autre.

MODIFIER

Toute information sur l'erreur

L'ID ne peut pas représenter la valeur: {_bsontype:\"ObjectID \", id:}

serait très utile. Je sens que cela me dit qu'il ne peut pas sérialiser un objet BSON .. mais ensuite, il l'affiche sérialisé. Même savoir quelle technologie (mongo? Mongoose? Graphql?) Générait l'erreur aiderait. Je n'ai aucune chance avec Google.

EDIT 2

Cela a été causé par une modification du paquetage graphql introduit récemment, et il y a un PR en attente de fusion qui le résout.

3
Alex McMillan

Je n'ai pas trouvé de problème et ai exécuté ce code avec l'une de mes bases de code existantes. Sauf que j'ai enveloppé la mutation dans la GraphQLObjectType.

const Mutation = new GraphQLObjectType({
    name: 'Mutation',
    fields: {
        addAccount: {
            type: AccountType,
            description: 'Create new account',
            args: {
                name: {
                    name: 'Account Name',
                    type: new GraphQLNonNull(GraphQLString)
                }
            },
            resolve: (root, args) => {
                const newAccount = new Account({
                    name: args.name
                });

                newAccount.id = newAccount._id;

                return new Promise((resolve, reject) => {
                    newAccount.save(err => {
                        if (err) reject(err);
                        else resolve(newAccount);
                    });
                });
            }
        }
    });

Pour obtenir l'exemple de travail: Clone the repo. Dans ce dépôt, l'application utilise v0.13.2 et vous utilisez v14.0.2 installé via npm i graphql. Rétrograder graphql à v0.13.2.

3
Shivam Pandey

J'ai utilisé ID et cela fonctionne bien! la cause de votre problème n'est pas du type id! c'est parce que vous lui donnez une mauvaise valeur: ObjectID('actuall id')

Pour résoudre ce problème, appelez la fonction toJson pour chaque donnée extraite ou ajoutez simplement une variable virtuelle id comme ceci:

YourSchema.virtual('id').get(function() {
    return this.toJSON()._id
}
1

Donc, ce que je viens de découvrir, c'est que _id est de type ObjectID mais semble implicitement transtypé en String. Donc, si vous définissez votre type d'identifiant de modèle mangouste sur String au lieu de mongoose.Schema.Types.ObjectId, il devrait alors fonctionner. En utilisant votre code actuel (tiré du tutoriel compose.com) qui copie _id en id, le résultat sera que, en mongo (après la sauvegarde), le _id sera de type ObjectID et votre modèle ID de type chaîne.

En d'autres termes, au lieu de cela

const Account = mongoose.model('Account', new mongoose.Schema({
  id: mongoose.Schema.Types.ObjectId,
  name: String
}));

Faire ceci

const Account = mongoose.model('Account', new mongoose.Schema({
  id: String,
  name: String
}));
0
Sinaesthetic