Apollo 中的缓存正在避免 GraphQL 解决多态关联

Posted

技术标签:

【中文标题】Apollo 中的缓存正在避免 GraphQL 解决多态关联【英文标题】:Cache in Apollo is avoiding GraphQL from resolving the polymorphic association 【发布时间】:2020-11-14 01:48:26 【问题描述】:

在 GraphQL(Apollo、Sequelize 和 SQLite)中,我使用字段来解析多态关联的模型类型。缓存时,出现解析关联的问题。

后端:

class AssignTModel extends Model 
    async getAction(options)       
        if (!this.actionType) return Promise.resolve(null);
            const mixinMethodName = `get$uppercaseFirst(this.actionType)`;
            const action=await this[mixinMethodName](options);
            if (action) action.myResolve=this.actionType;
            return action;
        
    
    AssignTModel.init(
        id: type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true     ,
    . . .
        actionId: type: Sequelize.INTEGER,
        actionType: type: DataTypes.STRING ,
    , sequelize,modelName: 'assignt');
    . . .
    AssignTModel.belongsTo(ReminderModel,  foreignKey: 'actionId', constraints: false );
    AssignTModel.belongsTo(ServiceModel,  foreignKey: 'actionId', constraints: false );
    const AssignT = sequelize.models.assignt;
    . . .
const typeDefs = gql`
 union Action = Reminder | Service
    type AssignT
        id:Int
  . . .

        action:Action
    
. . .
    type Query 
      . . .
      action(id:Int):[Action],
    . . .

  const resolvers = 
. . .
    Action:
        __resolveType(obj, context, info)
          if(obj && obj.myResolve && obj.myResolve === "reminder" )
            return 'Reminder';
          

          if(obj && obj.myResolve && obj.myResolve === "service" )
            return 'Service';
          
          return null;
        ,
    ,
. . .
    AssignT: 
        . . .
        action: async (assignt) => assignt.getAction(),
    ,

前端:

在 React.JS 应用程序中,当我在查询上启用缓存时,我在解决多态关联时遇到了问题:

FORM_QUERY = gql`query ($id:Int)
                  nodes:assignT(id:$id)
                    id
                    . . .
                    action 
                        ... on Reminder
                            id
                            label
                          
                        ... on Service
                            id
                            label
                          
                    
                  
                `;

Not OK --> <Query query=FORM_QUERY variables=id:id fetchPolicy="cache-and-network">

OK --> <Query query=FORM_QUERY variables=id:id fetchPolicy="no-cache">

GraphQL Playground 上没有出现这个问题,这就是我怀疑缓存的原因。

如何在维护缓存的同时解决这个问题?

【问题讨论】:

我想我也有同样的问题。您能否提供有关它引发的错误的更多详细信息? @Thomas 它在操作为提醒时有效,并且在操作为服务时根本不加载数据(我得到空数据),并针对在提醒中定义但不在服务中定义的字段发出警告。跨度> 【参考方案1】:

找到并解决。我正在发布答案,以便它可以帮助面临同样问题的人。

问题在于没有使用 IntrospectionFragmentMatcher。 事实上,我已经看到了这个警告,但我打算稍后解决它,并没有直接链接到我的问题。

解决方法如下:

import  InMemoryCache, NormalizedCacheObject,IntrospectionFragmentMatcher  from 'apollo-cache-inmemory';
import ApolloClient from "apollo-boost";

const possibleTypes = 
  __schema: 
    types: [
        kind: 'UNION',
        name: 'Action',
        possibleTypes: [
           name: 'Service' ,
           name: 'Reminder' ,
        ]
      ,
    ]
  ,


const fragmentMatcher = new IntrospectionFragmentMatcher(
    introspectionQueryResultData: possibleTypes
)
const cache = new InMemoryCache(
                    fragmentMatcher
                )
const uri= 'http://localhost:4000/';
const link = createHttpLink( uri, fetch );
const client= new ApolloClient(
  cache,
  link
);

【讨论】:

以上是关于Apollo 中的缓存正在避免 GraphQL 解决多态关联的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL + Apollo - 如何强制进行查询,似乎正在缓存一些东西

(GraphQL) - 为啥 Apollo 先检查缓存,然后再做其他事情?

更新 apollo 缓存而不调用 graphql 服务器(apollo v3.3)

使用 Apollo 和 GraphQL 缓存而不是 Vuex?

Apollo GraphQL,有没有办法在查询期间操作正在写入缓存的数据?

在哪里查看 Apollo 服务器 express GraphQL 缓存?