You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Notion Search API无法返回账号全部页面ID问题求助

Notion API Search端点返回结果数量不稳定问题

我正在开发一款基于Notion API的应用,目标是获取账号下所有页面ID。我已经实现了递归函数处理POST https://api.notion.com/v1/search的分页机制,会一直请求直到没有下一页,但奇怪的是每次调用得到的结果数量每天都在变:上个月能拿到约250个页面ID,昨天只拿到71个,但我确定账号里的页面远不止这些。

编辑1:
最近几天运行代码又拿到了200+结果,之前猜测的“只能检索近三个月页面”已经排除,现在完全找不到原因。

附上我的代码:

import axios from 'axios';
import dotenv from 'dotenv';
import os from 'os';

const notion = new Client({
    auth: NOTION_TOKEN,
});

// 获取UID列表(递归分页)
const fetchListOfUids = async (nextPageId, blockList = []) => {
    const payload = nextPageId ? { start_cursor: nextPageId } : {};

    try {
        const { results, has_more, next_cursor } = await notion.search({
            ...payload,
        });
        const accumulatedBlockList = [...blockList.concat(results)];

        // 有下一页则继续请求
        if (has_more) {
            return fetchListOfUids(next_cursor, accumulatedBlockList);
        }
        return accumulatedBlockList;
    } catch (err) {
        console.log({ err });
    }
};

// 主函数
(async () => {
    createDownloadDirectory();
    try {
        const blockList = await fetchListOfUids();
        blockList.map(async (block) => {
            setTimeout(async () => {
                await downloadAsMarkdown(block);
            }, 1000);
        });
    } catch (err) {
        console.log({ err });
    }
})();

可能的原因及解决方案

1. 默认过滤规则导致结果不全

Notion的search端点默认只会返回可搜索范围内的内容,以下情况会导致页面被过滤:

  • 页面在回收站(未彻底删除的回收站内容默认不参与搜索)
  • 集成token无该页面访问权限(比如页面权限被修改、共享链接过期)
  • 页面属于数据库深层条目,默认搜索未遍历到

解决办法:
在搜索请求中添加明确的过滤和排序规则,锁定页面类型并固定排序逻辑,避免结果波动:

await notion.search({
    ...payload,
    filter: {
        property: "object",
        value: "page" // 只搜索页面类型
    },
    sort: {
        direction: "ascending",
        timestamp: "created_time" // 固定排序规则,防止分页漏项
    }
});

2. 递归分页的稳定性问题

递归逻辑本身没问题,但API偶发的延迟或网络波动可能导致has_more/next_cursor返回不准确,中断后续请求;另外递归出错时无重试机制,会直接终止获取流程。

解决办法:
换成循环实现分页,同时添加日志和重试逻辑,便于排查问题:

const fetchListOfUids = async () => {
    const blockList = [];
    let nextPageId = null;
    do {
        try {
            const { results, has_more, next_cursor } = await notion.search({
                start_cursor: nextPageId,
                filter: { property: "object", value: "page" }
            });
            blockList.push(...results);
            nextPageId = has_more ? next_cursor : null;
            console.log(`本次获取${results.length}条,累计${blockList.length}条`);
        } catch (err) {
            console.error(`请求失败,2秒后重试:`, err);
            await new Promise(resolve => setTimeout(resolve, 2000));
        }
    } while (nextPageId);
    return blockList;
};

3. API限流导致部分请求失效

Notion API有速率限制(每秒最多3次请求,每分钟最多1000次),如果请求频率过高,会被临时限流,导致部分请求返回空结果或不完整分页数据。

解决办法:
在分页请求之间添加固定延迟,避免触发限流:

// 在每次搜索请求后添加延迟
await new Promise(resolve => setTimeout(resolve, 500));

同时可以检查响应头的X-RateLimit-Remaining字段,实时监控剩余请求额度。

4. Notion搜索索引更新延迟

Notion的搜索索引不是实时同步的,页面创建、修改后可能需要一段时间才能被API搜索到;部分空页面或含大量嵌入内容的页面也可能被标记为不可搜索,导致不同时间点结果数量波动。

解决办法:

  • 手动在Notion客户端搜索,对比API返回结果,确认是否存在客户端能搜到但API搜不到的页面
  • 在搜索请求中添加query: ""空查询,强制返回所有可搜索页面

内容的提问来源于stack exchange,提问作者Andy Lu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:18:25