Apollo Client+GraphQL+Prisma如何通过非ID字段查询数据?
解决方案
1. 修正查询字段名错误
你的Prisma模型是RecordingFile,但查询里误用了videoFile,这是核心错误之一。Prisma生成的GraphQL查询字段名遵循模型名的小驼峰规则,所以正确的字段名应该是recordingFile/recordingFiles,而非videoFile。但默认情况下,单个recordingFile查询仅支持id参数,这也是你改完字段名后仍报错的原因。
2. 实现按path字段查询
要通过非ID字段(path)查询,需要以下操作:
步骤1:给path字段添加唯一约束(可选但推荐)
如果你的path字段全局唯一,先在Prisma Schema中添加@unique约束,这样能利用findUnique实现高效查询:
model RecordingFile { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid name String path String @unique // 添加唯一约束 duration Float size Int tag Tag[] createdAt DateTime @default(now()) @db.Timestamptz(6) updatedAt DateTime @default(now()) @updatedAt @db.Timestamptz(6) }
执行命令更新数据库并重新生成Prisma Client:
npx prisma migrate dev npx prisma generate
步骤2:自定义GraphQL查询Resolver
若使用Prisma + Apollo Server组合,需添加自定义查询字段并编写Resolver:
更新GraphQL Schema定义
type Query { # 保留默认按id查询的字段 recordingFile(id: String!): RecordingFile # 添加按path查询的自定义字段 recordingFileByPath(path: String!): RecordingFile }
编写Resolver逻辑
// 假设已初始化Prisma Client实例为prisma const resolvers = { Query: { recordingFileByPath: async (_, { path }) => { // path唯一时用findUnique,非唯一则改用findFirst return await prisma.recordingFile.findUnique({ where: { path } }); } } };
步骤3:修改前端查询语句
现在可以在React组件中使用新的查询字段:
const FIND_BY_PATH = gql` query GetExisting($path: String!) { recordingFileByPath(path: $path) { id name path } } `
3. 备选方案:使用列表查询过滤
若不想自定义Resolver,也可以通过recordingFiles列表查询的where参数过滤结果:
const FIND_BY_PATH = gql` query GetExisting($path: String!) { recordingFiles(where: { path: $path }) { id name path } } `
这种方式会返回所有匹配path的记录,你可以在前端取第一个结果使用。
修正后的React组件代码
import React from "react"; import { gql, useQuery } from "@apollo/client"; interface NodeTableRowParams { data: { file: { name: string, path: string // ... 其他字段 } // ... 其他字段 } } const FIND_BY_PATH = gql` query GetExisting($path: String!) { recordingFileByPath(path: $path) { id name path } } ` const NodeTableRow: React.FC<NodeTableRowParams> = ({data}) => { const { loading: loading_findByPath, error: error_findByPath, data: data_findByPath} = useQuery(FIND_BY_PATH, { variables: { path: data.file.path } }); if (loading_findByPath) return <div>加载中...</div>; if (error_findByPath) return <div>错误:{error_findByPath.message}</div>; return ( <div id="file-list"> <FileData data={data}/> {/* 可使用data_findByPath.recordingFileByPath获取查询结果 */} </div> ); }; export default NodeTableRow;
内容的提问来源于stack exchange,提问作者Jeff Wilkerson
相关产品推荐
相关产品推荐

