首页 > 解决方案 > Mongoose + GraphQL 无法填充模型

问题描述

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

我有一个在 localhost 上运行 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

根据猫鼬文档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
    }
  }
}

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

标签: javascriptmongodbmongoosegraphqlapollo-server

解决方案


的第一个参数mongoose.model()必须是您的模型所针对的集合的单数名称。Mongoose 会自动查找您的模型名称的复数、小写版本,因此对于您的情况:

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()

推荐阅读