You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GraphQL前端返回重复数据但后端正常,求排查解决

前端GraphQL查询返回重复数据的解决方法

问题场景

用GraphQL Sandbox查询MongoDB数据时,能返回3条符合条件的唯一Player数据;但前端通过useQuery调用相同查询,得到的数组里是同一条数据重复3次(数量等于limit设置值)。移除resolver里的id查询条件后,前端能正常获取不同数据,同页面其他集合的类似功能无异常。

相关代码片段:

Resolver

players: async (parent, { id }) => {
  return Player.find({ id: id }).sort({ game_id: -1 }).limit(3);
},

TypeDefs

type Player {
  _id: ID
  game_id: Int
  id: String
  player_name: String
  PTS: Int
}

type Query {
  players(id: String): [Player]
}

前端查询

export const GET_PLAYER = gql`
query Players($playersId: String) {
  players(id: $playersId) {
    _id
    game_id
    player_name
    PTS
  }
}

问题原因

Apollo Client默认会用对象的id或_id字段作为缓存的唯一标识键。你的Player类型中,业务用的id字段是多个文档共享的值(查询条件就是这个id),导致Apollo Client把所有返回的Player实例都判定为同一个实体,缓存时后面的结果覆盖前面的,最终前端读取缓存时重复返回同一条数据。而Sandbox默认不启用客户端缓存,所以能返回正确结果。

解决方案

方案1:指定Player类型的缓存键为_id

修改Apollo Client的缓存配置,明确告诉它用MongoDB的唯一主键_id作为Player实体的标识:

import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: '/graphql',
  cache: new InMemoryCache({
    typePolicies: {
      Player: {
        keyFields: ['_id'], // 强制使用_id作为缓存唯一键
      },
    },
  }),
});

方案2:查询时禁用缓存(临时调试用)

在useQuery中设置fetchPolicy为network-only,强制每次从服务器获取数据,不使用缓存:

const { data } = useQuery(GET_PLAYER, {
  variables: { playersId: '你的目标ID' },
  fetchPolicy: 'network-only',
});

注意:这个方案适合快速验证问题,但不推荐在生产环境长期使用,会失去缓存带来的性能优势。

方案3:重命名业务用的id字段

把类型定义中业务相关的id字段改名(比如player_id),避免和Apollo默认的缓存键字段冲突:

  1. 修改TypeDefs:
type Player {
  _id: ID
  game_id: Int
  player_id: String # 原id字段改名
  player_name: String
  PTS: Int
}

type Query {
  players(player_id: String): [Player] # 同步修改查询参数名
}
  1. 修改Resolver:
players: async (parent, { player_id }) => {
  return Player.find({ id: player_id }).sort({ game_id: -1 }).limit(3);
},
  1. 修改前端查询:
export const GET_PLAYER = gql`
query Players($playersId: String) {
  players(player_id: $playersId) {
    _id
    game_id
    player_name
    PTS
  }
}

验证

修改后再次调用前端查询,应该能获取到3条不同的Player数据,和Sandbox的结果一致。

内容的提问来源于stack exchange,提问作者evanhu96

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:40:49