如何通过Cloud Firestore REST API更新指定嵌套字段?
Firestore REST API 仅更新嵌套对象特定字段的正确方式
场景与问题
我用GAS开发基于Firebase Cloud Firestore的Google Docs扩展,GROUPS集合下的Test文档结构如下:
{ "DISPLAY_IDS": { "TYPE1": [1,2,3], "TYPE2": [4,5,6], "TYPE3": [7,8,9] } }
需求是仅更新TYPE2对应的整个数组(不追加元素),用Firestore JS SDK可以直接通过点符号实现:
firestore.collection("GROUPS").document("Test").update({ "DISPLAY_IDS.TYPE2": [10,11,12] });
但切换到REST API时遇到三个问题:
- 用点符号作为字段名发PATCH请求,会在
DISPLAY_IDS外部创建新的DISPLAY_IDS.TYPE2顶层字段; - 更新整个
DISPLAY_IDS对象并设置updateMask.fieldPaths=DISPLAY_IDS,会覆盖TYPE1、TYPE3的内容; - 组合上述两种方式的请求没有任何更新效果。
正确解决方案
Firestore REST API处理嵌套字段更新时,需要同时构造嵌套格式的请求体,并在updateMask中指定完整的嵌套字段路径,具体步骤如下:
1. 请求URL与参数
发送PATCH请求到以下URL,替换[PROJECT_ID]为你的Firebase项目ID,并在query参数中指定updateMask.fieldPaths=DISPLAY_IDS.TYPE2:
https://firestore.googleapis.com/v1/projects/[PROJECT_ID]/databases/(default)/documents/GROUPS/Test?updateMask.fieldPaths=DISPLAY_IDS.TYPE2
2. 请求体格式
请求体需要按照Firestore REST API的结构化格式编写,不能直接用点符号字段名,而是嵌套构造mapValue和arrayValue:
{ "fields": { "DISPLAY_IDS": { "mapValue": { "fields": { "TYPE2": { "arrayValue": { "values": [ {"integerValue": 10}, {"integerValue": 11}, {"integerValue": 12} ] } } } } } } }
3. GAS代码示例
结合GAS的UrlFetchApp实现完整的更新逻辑:
function updateNestedTypeArray() { const projectId = "你的Firebase项目ID"; const targetDocPath = "GROUPS/Test"; const newType2Array = [10, 11, 12]; // 要更新的新数组 // 构造符合Firestore REST格式的请求体 const requestBody = { fields: { DISPLAY_IDS: { mapValue: { fields: { TYPE2: { arrayValue: { values: newType2Array.map(num => ({ integerValue: num })) } } } } } } }; const fetchOptions = { method: "PATCH", contentType: "application/json", headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() }, payload: JSON.stringify(requestBody) }; // 拼接请求URL,指定updateMask const apiUrl = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${targetDocPath}?updateMask.fieldPaths=DISPLAY_IDS.TYPE2`; // 发送请求 const response = UrlFetchApp.fetch(apiUrl, fetchOptions); console.log("更新结果:", response.getContentText()); }
关键说明
- Firestore REST API不支持在请求体中直接使用点符号表示嵌套字段,必须通过
mapValue逐层嵌套构造; updateMask.fieldPaths必须精确指定到要更新的嵌套字段(DISPLAY_IDS.TYPE2),这样Firestore才会仅更新该字段,而不会覆盖整个DISPLAY_IDS对象;- 数组类型需要用
arrayValue包裹,每个元素要对应类型(比如整数用integerValue,字符串用stringValue)。
内容的提问来源于stack exchange,提问作者Yuval.R
相关产品推荐
相关产品推荐

