こんにちは。
Notionの案件でNotionのタイトル周りでの癖に悩まされた話と、解決策を書かせていただきます。
Notion APIでページ一覧を取得
Notion APIでは以下のようにしてページ一覧を取得できます。
取得できるのは、インテグレーションをコネクトしたページ、およびインテグレーションをコネクトしたデータベースにぶら下がっているページです。
実際に使用したコードを適当にバラしただけですので、見にくい上に実際に動くかどうか分かりませんが、ご愛嬌で笑ってご容赦いただければと思います。
const token="";
const NOTION_VERSION="";
_post(endPoint, payload) {
const options = {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token,
'Notion-Version': NOTION_VERSION,},
}
if (payload)
options.payload = JSON.stringify(payload);
const resp = UrlFetchApp.fetch(endPoint, options)
const result = JSON.parse(resp.getContentText());
return result;
}
search(filter = null, start_cursor = undefined) {
if (!filter) filter = {};
filter.start_cursor = start_cursor; //undefinedはAPIが許容する
let result = this._post(`https://api.notion.com/v1/search`, filter);
//続きがあれば取得
if (result.has_more) {
return [...result.results, ...this.search(filter, result.next_cursor)];
}
return result.results;
}
Notion APIの癖
上記のようにしてページ一覧を取得できるのはいいのですが、ここから難がありました。
タイトルが、、、
Notion APIのドキュメントより引用です。propertiesに関する記述です。
If parent.type is "page_id" or "workspace", then the only valid key is title.
If parent.type is "database_id", then the keys and values of this field are determined by the >properties of the database this page belongs to.
https://developers.notion.com/reference/page
これによると、親のタイプがpage_idもしくはworkspaceの場合のみ、確実にtitle属性がつくそうです。
しかし親のタイプがdatabase_idなら、そのデータベースに依存するとあります。
始め私のテスト環境では、親がデータベースの場合取得したページオブジェクトの「名前」属性で取れてたんですね。ですがそれが問題で、たまたま私のデータベースのタイトル部分が「名前」になっていただけで、そうでない場合もあるわけです。
そこで解決策として、propertiesオブジェクト全てを走査し、type属性がtitleのものを抽出する必要があるわけです。具体的なコードは以下になります。
/**
* アイテムからタイトルを取得
*/
function getTitle(item) {
if (item.object == "database")
return item.title[0].plain_text;
for (let prp of Object.values(item.properties)) {
if (prp.type == "title") {
return prp.title[0].plain_text;
}
}
}
うーむ、なんと。初めからtitle属性付けておいてくれたら良いのにと思います。
ちなみにtitleがなぜ配列になっているのか、いまだに理解できていません。
一つのページまたはデータベースで、複数のタイトルが付く事ってあるのでしょうか。
詳しい方、コメントで教えていただけましたらこれ幸いです。