我正在开发一个允许用户上传大型数据集的应用程序。上传者有一个“草稿”版本,可以在UI中进行编辑,然后发布草稿的快照,所有用户都可以看到。仅当上传者已登录时,才应查询草稿文件。
虽然非编辑特权用户看不到草稿,但该应用仍会查询其整个文件集,这使得获取数据集页面的速度非常慢。
查询中包含“草稿”数据的片段,包括有条件不需要的文件。如果我省略了片段中的文件,则该组件适用于所有用户...但是上载器无法获取其草稿文件。因此,这就是我该死的事情,如果我不感到困惑,那就是该死的,而我对graphql和apollo缺乏经验的确在这里闪耀。
这是查询和附带的钩子:
export const getDatasetPage = gql`
query dataset($datasetId: ID!) {
dataset(id: $datasetId) {
id
created
public
following
starred
...DatasetDraft
...DatasetPermissions
...DatasetSnapshots
...DatasetIssues
...DatasetMetadata
...DatasetComments
uploader {
id
name
email
}
analytics {
downloads
views
}
onBrainlife
}
}
${DatasetQueryFragments.DRAFT_FRAGMENT}
${DatasetQueryFragments.PERMISSION_FRAGMENT}
${DatasetQueryFragments.DATASET_SNAPSHOTS}
${DatasetQueryFragments.DATASET_ISSUES}
${DatasetQueryFragments.DATASET_METADATA}
${DATASET_COMMENTS}
`
export const DatasetQueryHook = ({ datasetId }) => {
const {
data: { dataset },
loading,
error,
} = useQuery(getDatasetPage, {
variables: { datasetId },
})
if (loading) {
return <Spinner text="Loading Dataset" active />
} else {
if (error) Sentry.captureException(error)
return (
<ErrorBoundary error={error} subject={'error in dataset page'}>
<DatasetQueryContext.Provider
value={{
datasetId,
}}>
<DatasetPage dataset={dataset} />
</DatasetQueryContext.Provider>
</ErrorBoundary>
)
}
}
这是片段:
export const DRAFT_FRAGMENT = gql`
fragment DatasetDraft on Dataset {
id
draft {
id
modified
readme
partial
description {
Name
Authors
DatasetDOI
License
Acknowledgements
HowToAcknowledge
Funding
ReferencesAndLinks
}
files { //when this is removed, it works...except for users with edit privileges
id
filename
size
}
summary {
modalities
sessions
subjects
subjectMetadata {
participantId
age
sex
group
}
tasks
size
totalFiles
dataProcessed
}
}
}
`
长话短说:如果用户没有编辑权限,则查询应省略草稿文件。我知道hasEdit的逻辑,但是我不知道如何使用指令来实现它。我甚至可以在片段上使用@skip
,即使可以,我是否可以有条件地传递其变量?我在文档中找不到与此相关的任何内容,并且不知所措。
答案 0 :(得分:2)
是的,指令可以在片段内使用,是的,您可以为此使用变量。
以下是使用SWAPI API的simple example:
query MyQuery ($showDate: Boolean!){
allFilms {
films {
...FilmFields
}
}
}
fragment FilmFields on Film {
id
title
releaseDate @include(if: $showDate)
}
这里要注意的一件事是,变量仍被定义为操作的一部分。这意味着,如果将片段放在单独的文件中,然后将其导入查询中,则需要确保A)操作实际上定义了变量,B)变量名正确。
还值得注意的是,实验支持将变量定义为片段的一部分。必须在服务器端显式启用它。如果您使用的是graphql-tag,它也是has to be explicitly enabled there as well。如果您使用的是makeExecutableSchema
或Apollo Server,则可以传入一个parseOptions
参数来启用此功能服务器端:
makeExecutableSchema({
typeDefs,
resolvers,
parseOptions: {
experimentalFragmentVariables: true,
},
})
然后您可以创建如下片段:
fragment FilmFields on Film ($showDate: Boolean!) {
id
title
releaseDate @include(if: $showDate)
}