Sanity GROQ如何获取文档中引用数组的关联草稿数据?
问题背景
定义了page类型文档,文档包含blocks数组,数组项为指向其他对象类型的引用。拉取page文档数据时,文档本身的草稿数据可正常返回,但数组内引用关联的草稿数据无法正常获取。
当前使用的可同时返回文档草稿与已发布数据的GROQ查询如下:
*[_type == "page" && slug.current == "${querySlug === '/' ? 'home' : querySlug}"] { _id, title, description, showSubNav, subNavigation[] -> {slug, title}, blocks[] -> { ..., heroCardBlock -> {...}, oneColumnContent -> {...}, featuredNews -> {...}, newsCategories[] -> {...}, newsList[] -> {..., selectedCategory -> {...}}, caseStudiesListSource[] -> {...}, } }
执行上述查询时,page文档的草稿、已发布版本均可正常返回,title、description、showSubNav等非引用字段的草稿数据可正常获取,但subNavigation、blocks这类存储引用的数组字段仅返回已发布数据,无法返回对应引用的草稿内容。
问题原因
GROQ默认的->引用解析逻辑,只会匹配_id不带drafts.前缀的已发布文档,不会自动关联引用对象的草稿版本。哪怕父文档查询到了草稿版本,其内部存储的引用字段默认记录的还是已发布文档的ID,不会自动指向草稿,因此默认解析拿不到引用的草稿数据。
解决方案
替换所有层级默认的->解析逻辑,解析引用时同时匹配「原引用ID对应的已发布文档」和「加drafts.前缀的草稿文档」,通过ID倒序排序优先取草稿,草稿不存在时自动回退到已发布版本。
调整后的完整查询如下:
*[_type == "page" && slug.current == "${querySlug === '/' ? 'home' : querySlug}"] { _id, title, description, showSubNav, // 重写subNavigation引用解析,优先取草稿 "subNavigation": subNavigation[] { "_key": _key, "data": *[_id in [@->_ref, "drafts." + @->_ref]] | order(_id desc)[0] { slug, title } }, // 重写blocks数组引用解析 "blocks": blocks[] { "_key": _key, "_type": _type, "data": *[_id in [@->_ref, "drafts." + @->_ref]] | order(_id desc)[0] { ..., // 处理block内部的单引用字段 "heroCardBlock": heroCardBlock != null => *[_id in [^.heroCardBlock._ref, "drafts." + ^.heroCardBlock._ref]] | order(_id desc)[0] {...}, "oneColumnContent": oneColumnContent != null => *[_id in [^.oneColumnContent._ref, "drafts." + ^.oneColumnContent._ref]] | order(_id desc)[0] {...}, "featuredNews": featuredNews != null => *[_id in [^.featuredNews._ref, "drafts." + ^.featuredNews._ref]] | order(_id desc)[0] {...}, // 处理block内部的数组引用字段 "newsCategories": newsCategories[] { "_key": _key, "data": *[_id in [@->_ref, "drafts." + @->_ref]] | order(_id desc)[0] {...} }, "newsList": newsList[] { "_key": _key, "data": *[_id in [@->_ref, "drafts." + @->_ref]] | order(_id desc)[0] { ..., // 处理嵌套的二级引用 "selectedCategory": selectedCategory != null => *[_id in [^.selectedCategory._ref, "drafts." + ^.selectedCategory._ref]] | order(_id desc)[0] {...} } }, "caseStudiesListSource": caseStudiesListSource[] { "_key": _key, "data": *[_id in [@->_ref, "drafts." + @->_ref]] | order(_id desc)[0] {...} } } } }
注意事项
- 排序逻辑利用了字符串排序规则:带
drafts.前缀的ID比普通ID长,倒序排列时会排在最前面,因此取排序后的第一条即可优先获得草稿版本,草稿不存在时自动返回已发布版本。 - 如果项目自定义了草稿前缀(不是默认的
drafts.),需要把查询中所有前缀字符串替换为项目实际配置值。 - 所有嵌套层级的引用都要使用上述逻辑重写解析,不能直接用默认
->,否则对应层级依然只会返回已发布数据。
内容的提问来源于stack exchange,提问作者Mutahhar Ahmad
相关产品推荐
相关产品推荐

