LINE予約「LUCA」の機能と料金はこちら

Airtable filterByFormulaでリンク先のレコードIDが0件になる原因と回避策

スプレッドシート・Airtable 実務ノート 公開 更新

AirtableのAPIで、リンク項目(Link to another record)をレコードIDで絞り込もうとして、1件も返ってこないことがあります。データはあるのに0件が返るので、「該当するレコードが無い」と勘違いしやすい落とし穴です。

この記事では、原因と、弊社のAirtableで実際に確かめた結果、回避策をまとめます。

この記事の結論

  • filterByFormula の数式の中では、リンク項目の値は「リンク先のレコードID」ではなく、「リンク先のプライマリフィールド(一番左の項目)の値」として扱われます。
  • そのため FIND('recXXXX', ARRAYJOIN({リンク項目})) は、データが何件あっても0件になります。
  • 確実なのは、リンク先のレコードをIDで取得して、逆向きのリンク項目を読む方法です。

実際に確かめた結果

弊社のAirtable(顧客のテーブルと、その履歴のテーブルがリンクで結ばれている構成)で、読み取りだけで確かめました。テーブル名と値は伏せています。

探し方 返ってきた件数
リンク先のレコードID(recで始まる)で探す
FIND('recXXXX', ARRAYJOIN({顧客}))
0件
リンク先の表示名で探す
FIND('表示名', ARRAYJOIN({顧客}))
4件
顧客のレコードをIDで取得し、逆向きのリンク項目(履歴)を読む 4件分のID

同じ相手を指しているのに、IDで探すと0件、表示名で探すと4件でした。逆向きのリンク項目から読んだ件数も4件で、表示名で探した結果と一致しています。

弊社では、この書き方で「0件なら該当なし」と判断する処理が、本番に7か所ありました。どれもエラーにはならず、静かに「無い」と答え続けていました。

なぜこうなるのか

APIでレコードを取得すると、リンク項目はレコードIDの配列で返ってきます。

{
  "id": "recAAAAAAAAAAAAAA",
  "fields": {
    "顧客": ["recBBBBBBBBBBBBBB"]
  }
}

一方、filterByFormula は、Airtableの画面で使う数式と同じように評価されます。数式の中でリンク項目を参照すると、画面に表示されている値、つまりリンク先のプライマリフィールドの値が並んだものとして扱われます。ARRAYJOIN で文字列にしても中身は表示名なので、レコードIDは含まれていません。

「APIの返り値ではID、数式の中では表示名」という食い違いが、0件の正体です。Airtableのコミュニティでも、filterByFormula ではレコードIDではなくプライマリフィールドの値を使う必要がある、と繰り返し説明されています。

回避策

1. 逆向きのリンク項目から読む(おすすめ)

Airtableでテーブル同士をリンクすると、相手のテーブルにも逆向きのリンク項目ができます。探したい相手のレコードをIDで1件取得すれば、そこに、自分を指しているレコードのIDが並んでいます。

GET https://api.airtable.com/v0/{baseId}/{顧客テーブル}/{顧客のレコードID}

"fields": {
  "履歴": ["recCCCCCCCCCCCCCC", "recDDDDDDDDDDDDDD"]
}

そのIDのレコードの中身が必要なら、RECORD_ID() を使って取得します。RECORD_ID() はそのテーブル自身のレコードIDを返すので、この比較は正しく当たります。弊社でも、この書き方で指定した2件がそのまま返ってくることを確かめています。

OR(RECORD_ID()='recCCCCCCCCCCCCCC', RECORD_ID()='recDDDDDDDDDDDDDD')

APIの呼び出しは1回増えますが、表示名の重複や名前の変更に影響されません。

2. 表示名で探す場合は、区切り記号で挟んで完全一致にする

表示名で探すときに FIND('山田', ARRAYJOIN({顧客})) のように書くと、「山田商事」のような別の相手まで当たります。区切り記号で前後を挟むと、名前がまるごと一致したときだけ当たります。

FIND(',山田商事,', ',' & ARRAYJOIN({顧客}, ',') & ',')

弊社の確認では、表示名の先頭2文字だけで探すと、挟まない書き方は4件当たり、挟む書き方は0件になりました。

ただし、この方法には次の弱点があります。

  • 同じ表示名の相手が複数いると、区別できません。
  • 表示名にカンマが含まれていると崩れます。区切り記号は、名前に出てこない文字に変えてください。
  • 相手の表示名を変更すると、当たらなくなります。

3. リンク先のレコードIDを数式項目で持たせる

リンク先のテーブルに数式 RECORD_ID() の項目を作り、元のテーブルにその項目のルックアップ項目を作る方法もあります。ルックアップ項目にはリンク先のレコードIDが並ぶので、IDで探せるようになります。Airtableのコミュニティで紹介されている方法です。

FIND('recBBBBBBBBBBBBBB', ARRAYJOIN({顧客のレコードID}))

テーブルに項目を足すことになるので、既存の運用やフォームに影響がないかを先に確かめてください。

4. 件数が少なければ、取ってから絞る

レコード数が少ないテーブルなら、条件を付けずに取得して、プログラムの側でIDを含むものだけ残す方法もあります。APIは1回に最大100件ずつ返すので、offset を使って最後まで読みます。

const hits = records.filter(r => (r.fields['顧客'] || []).includes('recBBBBBBBBBBBBBB'));

n8nで使うときの注意

n8nのAirtableノードで「Filter By Formula」を使う場合も、式はAirtableのAPIに渡されるので、同じように0件になります。結果が0件でもエラーにはならず、後ろのノードが動かないまま成功扱いで終わるので、気づきにくくなります。

0件が返ってきたら、「データが無い」と決めつけずに、まず式の書き方を疑ってください。

まとめ

  • 数式の中のリンク項目は、レコードIDではなく表示名として扱われます。
  • だから FIND('recXXXX', ARRAYJOIN({リンク項目})) は0件になります。
  • 確実なのは、相手のレコードをIDで取得して、逆向きのリンク項目を読む方法です。
  • 表示名で探すなら、区切り記号で挟んで完全一致にします。

参考

Airtableとn8nでつくる仕組みのご相談

「データはあるのに0件になる」「知らないうちに処理が止まっている」といった不具合の点検や、Airtableとn8nを使った業務の自動化の仕組みづくりをお引き受けしています。

お問い合わせはこちら

この記事を書いた人

貫名 孝夫(マルタマーケティング株式会社 代表取締役)。n8nで140本を超えるワークフローを本番で動かしながら、実際に起きた不具合と直し方を記録しています。会社概要