簡體   English   中英

阿波羅服務器+續集錯誤不可為空的字段

[英]apollo server + sequelize error non-nullable field

我正在運行一個 apollo 服務器,它的 sequelize 為 orm 到 postgres 數據庫。 這是模式:

    type Tag {
        id: ID!
        name: String!
    }

    type Service {
        id: ID!
        name: String!
        slug: String!
        tags: [Tag!]!
    }

解析器:

        findServicesByTag: async(_, { tag }, { models }) => {
            const res = await models.Service.findAll({
                where: {
                    '$Tags.name$': tag
                }
                ,include: [
                    {
                        model: models.Tag,
                        as: 'Tags'
                    }
                ]
            })
            console.log(res)
            return res
        }

但是當執行這個查詢時

query {
  findServicesByTag(tag: "restaurant")
  {
    id name slug
    tags {
      name
    }
  }
}

我收到消息“無法為不可為空的字段 Service.id 返回 null。”

console.log 指令打印此數據:

[ Service {
    dataValues: { id: 1, name: 'Restaurant X', Tags: [Array] },
    _previousDataValues: { id: 1, name: 'Restaurant X', Tags: [Array] },
    _changed: Set {},
    _options:
     { isNewRecord: false,
       _schema: null,
       _schemaDelimiter: '',
       include: [Array],
       includeNames: [Array],
       includeMap: [Object],
       includeValidated: true,
       attributes: [Array],
       raw: true },
    isNewRecord: false,
    Tags: [ [Tag] ] },
  Service {
    dataValues: { id: 2, name: 'Restaurant Y', Tags: [Array] },
    _previousDataValues: { id: 2, name: 'Restaurant Y', Tags: [Array] },
    _changed: Set {},
    _options:
     { isNewRecord: false,
       _schema: null,
       _schemaDelimiter: '',
       include: [Array],
       includeNames: [Array],
       includeMap: [Object],
       includeValidated: true,
       attributes: [Array],
       raw: true },
    isNewRecord: false,
    Tags: [ [Tag] ] } ]

似乎 apollo 無法處理此數據,它不會查詢后續標簽實體。

您應該使用instance.get方法來獲取dataValues

Model 實例使用dataValues屬性的概念進行操作,該屬性存儲實例表示的實際值。

然后,您需要為 model 關聯定義alias: 'tags' ,因為 graphql 類型為 object - service具有tags字段。 確保它們被正確映射。

使用"sequelize": "^5.21.3""apollo-server": "^2.19.0"的工作示例。

model.ts

import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';

class Service extends Model {}
Service.init(
  {
    id: {
      primaryKey: true,
      type: DataTypes.INTEGER,
      autoIncrement: true,
      allowNull: false,
    },
    name: DataTypes.STRING,
    slug: DataTypes.STRING,
  },
  { sequelize },
);

class Tag extends Model {}
Tag.init(
  {
    id: {
      primaryKey: true,
      type: DataTypes.INTEGER,
      autoIncrement: true,
      allowNull: false,
    },
    name: DataTypes.STRING,
  },
  { sequelize },
);

Service.belongsToMany(Tag, { through: 'Service_Tag', as: 'tags' });
Tag.belongsToMany(Service, { through: 'Service_Tag', as: 'services' });

(async function test() {
  try {
    await sequelize.sync({ force: true });
    //seed
    await Service.bulkCreate(
      [
        { name: 'Restaurant X', slug: 'a', tags: [{ name: 'restaurant' }, { name: 'b' }] },
        { name: 'Restaurant Y', slug: 'b', tags: [{ name: 'c' }] },
        { name: 'Restaurant Z', slug: 'c', tags: [{ name: 'restaurant' }] },
      ],
      { include: [{ model: Tag, as: 'tags' }] },
    );
  } catch (error) {
    console.log(error);
  }
})();

export { Service, Tag };

app.ts

import { ApolloServer, gql } from 'apollo-server';
import * as models from './model';

const typeDefs = gql`
  type Tag {
    id: ID!
    name: String!
  }

  type Service {
    id: ID!
    name: String!
    slug: String!
    tags: [Tag!]!
  }

  type Query {
    findServicesByTag(tag: String!): [Service]!
  }
`;

const resolvers = {
  Query: {
    async findServicesByTag(_, { tag }, { models }) {
      const res = await models.Service.findAll({
        where: {
          '$tags.name$': tag,
        },
        include: [
          {
            model: models.Tag,
            as: 'tags',
          },
        ],
      });
      const data = res.map((v) => v.get({ plain: true }));
      return data;
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: {
    models,
  },
});

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

使用curl測試 GraphQl 查詢:

 ⚡  curl 'http://localhost:4000/graphql' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'Origin: chrome-extension://flnheeellpciglgpaodhkhmapeljopja' --data-binary '{"query":"\nquery{\n  findServicesByTag(tag: \"restaurant\"){\n    id\n    name\n    slug\n    tags {\n      \tname\n\t\t}\n  }\n}","variables":{}}' --compressed
{"data":{"findServicesByTag":[{"id":"1","name":"Restaurant X","slug":"a","tags":[{"name":"restaurant"}]},{"id":"3","name":"Restaurant Z","slug":"c","tags":[{"name":"restaurant"}]}]}}

數據庫中的數據記錄:

node-sequelize-examples=# select * from "Service";
 id |     name     | slug 
----+--------------+------
  1 | Restaurant X | a
  2 | Restaurant Y | b
  3 | Restaurant Z | c
(3 rows)

node-sequelize-examples=# select * from "Tag";
 id |    name    
----+------------
  1 | restaurant
  2 | b
  3 | c
  4 | restaurant
(4 rows)
node-sequelize-examples=# select * from "Service_Tag";
 ServiceId | TagId 
-----------+-------
         1 |     1
         1 |     2
         2 |     3
         3 |     4
(4 rows)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM