Mongoose + GraphQL 无法填充模型 [重复]

Posted

技术标签:

【中文标题】Mongoose + GraphQL 无法填充模型 [重复]【英文标题】:Mongoose + GraphQL cannot populate model [duplicate] 【发布时间】:2020-05-21 14:52:45 【问题描述】:

嗯,我知道有很多关于这个问题的问题,但他们的解决方案都不适合我,或者我找不到正在发生的事情。

我有一个在本地主机上运行 Apollo Server + Mongoose 的后端服务器。我的问题是我无法填充或创建集合,因为我得到了:

错误"ID cannot represent value: <Buffer 5e 38 65 18 f1 e3 f5 43 10 d4 c1 45>"

这是模型:

import mongoose from 'mongoose';
const Float = require('mongoose-float').loadType(mongoose);

const gastoSchema = new mongoose.Schema(
    descripcion: String,
    importe: Float,
    proveedor: 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Proveedor'
    ,
, 
    timestamps: 
        createdAt: 'fechaCreacion',
        updatedAt: 'fechaActualizacion'
    
);

export default mongoose.model('gastos', gastoSchema);

这是我的类型定义:

import  gql  from 'apollo-server';

export default gql`
    type Gasto 
        id: ID
        descripcion: String
        importe: Float
        proveedor: Proveedor
    

    extend type Query 
        gastos: [Gasto]
        gasto(id: ID!): Gasto
    

    extend type Mutation 
        crearGasto(descripcion: String, importe: Float, proveedor: ID): Gasto
        actualizarGasto(id: ID!, descripcion: String, importe: Float, proveedor: ID): Gasto
        eliminarGasto(id: ID!): String
    
`;

这是我的解析器:

import Gasto from '../models/Gasto';

export default 
    Query: 
        gastos: () => Gasto.find().populate('proveedores').exec(),
        gasto: (_,  id ) => Gasto.findById(id).populate('proveedores').exec()
    ,
    Mutation: 
        crearGasto: (_, input) => Gasto.create(input),
        actualizarGasto: (_, input) => Gasto.findOneAndUpdate(input),
        eliminarGasto: (_,  id ) => Gasto.findOneAndDelete(id)
    
;

尝试 1

我已尝试对我的模型定义进行此更改,但没有成功:

import mongoose from 'mongoose';
const Float = require('mongoose-float').loadType(mongoose);
const ObjectId = require('mongoose').Types.ObjectId;

ObjectId.prototype.valueOf = function()  return this.toString(); 

const gastoSchema = new mongoose.Schema(
    descripcion: String,
    importe: Float,
    proveedor: 
        type: ObjectId,
        ref: 'Proveedor'
    ,
, 
    timestamps: 
        createdAt: 'fechaCreacion',
        updatedAt: 'fechaActualizacion'
    
);

export default mongoose.model('gastos', gastoSchema);

尝试 2

根据mongoose documentation,我也尝试在populate('proveedores')(复数)、populate('proveedor') (singular)之间切换,但错误发生了变化:

import Gasto from '../models/Gasto';

export default 
    Query: 
        gastos: () => Gasto.find().populate('proveedor').exec(),
        gasto: (_,  id ) => Gasto.findById(id).populate('proveedor').exec()
    ,
    Mutation: 
        crearGasto: (_, input) => Gasto.create(input),
        actualizarGasto: (_, input) => Gasto.findOneAndUpdate(input),
        eliminarGasto: (_,  id ) => Gasto.findOneAndDelete(id)
    
;

错误"message": "Schema hasn't been registered for model \"Proveedor\".\nUse mongoose.model(name, schema)"

以防万一这是我的Proveedor 模型定义:

import mongoose from 'mongoose';

const proveedorSchema = new mongoose.Schema(
    nombre: 
        type: String,
        required: true
    ,
    telefono: String,
    direccion: String,
    email: String,
, 
    timestamps: 
        createdAt: 'fechaCreacion',
        updatedAt: 'fechaActualizacion'
    
);

export default mongoose.model('proveedores', proveedorSchema);

这是我在 GraphQL 操场上查询的内容:

query 
  gastos 
    id
    importe
    proveedor 
      id
      nombre
    
  

有什么线索吗?提前致谢。

【问题讨论】:

完成...没有任何改变。 请参阅链接帖子中提供的答案。您也可以为每个 id 字段添加一个解析器,例如 obj => obj._id.toString() 【参考方案1】:

mongoose.model() 的第一个参数必须是the singular name of the collection your model is for. Mongoose automatically looks for the plural, lowercased version of your model name,所以对于你的情况:

mongoose.model('Gasto', gastoSchema);
mongoose.model('Proveedor', proveedorSchema);

接下来,您必须为 proveedor 字段和 .exec() 添加解析器以执行 mongoose 查询

import Gasto from '../models/Gasto';
import Proveedor from '../models/Proveedor';

export default 

export default 
  Gasto: 
    proveedor: ( proveedor ) => Proveedor.findById(proveedor).exec() 
  ,
  Query: 
    gastos: () => Gasto.find().exec(),
    gasto: (_,  id ) => Gasto.findById(id).exec()
  ,
  Mutation: 
    crearGasto: (_, input) => Gasto.create(input).exec(),
    actualizarGasto: (_, input) => (_,  id: _id, ...input ) => 
    Gasto.findOneAndUpdate( _id , input,  new: true ).exec(),
    eliminarGasto: (_,  id: _id ) => Gasto.findOneAndDelete( _id ).exec()
  

注意actualizarGasto 的解析器必须是

actualizarGasto: (_,  id: _id, ...input ) => Gasto.findOneAndUpdate( _id , input,  new: true ).exec()

【讨论】:

以上是关于Mongoose + GraphQL 无法填充模型 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

NestJS + Mongoose + GraphQL:“填充”不起作用

Mongoose 无法进行深度填充

使用 graphql 和 nodejs 填充猫鼬模式

如何在不创建 Mongoose 模型的情况下将 GraphQL 与 Mongoose 和 MongoDB 一起使用

graphql + mongoose + typescript,如何减少重复的模型定义

从 Rest(Express) 迁移到 GraphQL:模型(mongoose) 在 graphQL 解析器中不起作用