Google Apps Script调用Notion API分页查询异常问题求助
解决Notion API分页查询异常问题
问题现象
开发Google Sheet配套的Apps Script时,使用Notion API查询数据库遇到分页异常:
- 结果少于100条时,首次请求正常
- 结果超过100条时,分页请求出现以下问题:
- 第二次请求
has_more始终为true,返回100条记录(预期仅剩余15条) - 携带filter参数时,重复获取前100条且
has_more一直为true - 不携带filter参数时,返回100条记录,仅前15条符合过滤条件,后续出现不符合要求的记录
- 第二次请求
问题原因分析
- 分页请求丢失过滤/排序参数:原代码第一次请求后将
payload设为null,导致后续请求无过滤条件,返回全量数据的分页结果而非过滤后的结果。 - 游标参数传递错误:Notion API要求
start_cursor放在请求体中,原代码将其放在UrlFetchApp的options顶层,导致分页游标未被正确识别。 - 日期格式不兼容:直接传递Date对象给Notion API,未转换为API可解析的ISO 8601格式字符串。
修正后的代码
function getNotionTaskCompletions () { // Setup URLs const url1 = "https://api.notion.com/v1/databases/xxxxxxx/query/"; const headers = { Authorization: "Bearer secret_xxxxxxx", "Content-Type": "application/json", "Notion-Version": "2022-06-28", }; // 计算30天前的日期,转换为ISO 8601格式字符串 const nowDate = new Date(Date.now()); const startDate = new Date(nowDate.getTime() - 30*1000*60*60*24).toISOString(); // 基础请求体,固定过滤和排序规则 const basePayload = { "filter": { "and": [ {"property": "Status", "status": { "equals": "Done", }, }, {"property": "Complete", "date": { "on_or_after": startDate, }, }, ] }, "sorts": [ { "property": "Complete", "direction": "ascending", } ] }; const tName = []; const tDate = []; let cursor = null; let hasMore = true; while (hasMore) { // 构建当前页请求体:基础参数 + 游标(如果存在) const requestPayload = { ...basePayload, ...(cursor && { start_cursor: cursor }) }; const options = { "muteHttpExceptions": true, "method": "post", "headers": headers, "payload": JSON.stringify(requestPayload), }; const response = UrlFetchApp.fetch(url1, options); const json = JSON.parse(response.getContentText()); hasMore = json.has_more; cursor = json.next_cursor; // 遍历当前页结果 for (const result of json.results) { const taskTitle = result.properties.Task.title[0]?.plain_text || ""; const completeDate = result.properties.Complete.date?.start.split("T")[0] || ""; tName.push(taskTitle); tDate.push(completeDate); Logger.log(`${taskTitle} - ${completeDate}`); } } // 清空目标区域 const dSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("data"); dSheet.getRange("K1:N300").clear({contentsOnly: true}); // 将数据写入表格 for (let i = 0; i < tName.length; i++) { dSheet.getRange(1 + i, 11).setValue(tName[i]); dSheet.getRange(1 + i, 12).setValue(tDate[i]); } }
关键修改说明
- 保留完整请求参数:每次分页请求都基于
basePayload构建,确保过滤和排序规则始终生效,避免返回非目标数据。 - 正确传递分页游标:将
start_cursor放入请求体中,符合Notion API的参数规范,确保分页逻辑正常运转。 - 日期格式标准化:将日期转换为ISO 8601字符串,避免API解析错误。
- 移除冗余校验:由于每次请求都携带过滤条件,返回结果必然符合要求,无需额外判断状态是否为"Done"。
- 代码优化:使用
let/const替代var,用for-of循环简化遍历,添加可选链操作符避免空值报错。
内容的提问来源于stack exchange,提问作者Rich Bair
相关产品推荐
相关产品推荐

