見出し画像

[kintone] 関連レコードを絞り込み検索対象にしたら混乱した話

こんにちは、キン担ラボの本橋です。

本橋です

ちょっとハマった関連レコードの罠についてメモを残しておきたいと思います。僕自身、お客さんからご相談いただいて「?」となりました。なんだか直感と合わない結果になるのです。

「絞り込む」は関連レコードも条件にできる

kintoneの絞り込み検索では関連レコードも条件に追加できます。そこで関連レコードを対象とした『≠(等しくない)』条件を追加したときに「?」が発生しました。

下の図でいうと、顧客名簿的なアプリ(左アプリ)のレコード一覧を見ているときに、石原さんの関連レコードである支払い記録(左アプリ)を対象とした絞り込みが可能です。

こんな関係がある2つのアプリで説明していきます

その挙動が直感に反していたことが理由でした。ここからはこのkintoneアプリ模式図を使って説明していきます。

アプリ模式図では、顧客名簿的なアプリの棒人間アイコンひとつで1レコード、支払い記録的なアプリでも書類アイコンひとつが1レコードを表しています。♢を頭に持った線を引いたものは関連レコード関係(今回は顧客IDで関連させています)です。

結論から言うと、関連レコードを対象に絞り込むと、条件は「全ての関連レコードに対する判定の論理和(OR)」として判定されます。

細かく見ていきたいと思います。

関連レコードを対象とした絞り込み

絞り込みダイアログで関連レコードを対象としたときに選べる条件は以下の5つです。

関連レコードを検索対象にできる

このとき、2つのグループに分けて考えることができます。

  • 「=等しい」と「次のキーワードを含む」

  • 「≠(等しくない)」と「次のキーワードを含まない」

前者は肯定形で、=や∈で表現されます。後者は「ない」という否定を含んだ条件です。後者の否定で事件は起きます。

順番に見ていきます。まずは素直に飲み込める肯定形から。

関連レコードの「=等しい」と「次のキーワードを含む」

kintoneの絞り込み条件で関連レコードに「キーワードを含む」条件を指定すると、関連レコードのいずれかに一つでも含まれていれば親レコードはヒットします。下の図でいうと、中村さんだけが該当します。

paypayの支払い記録を持つのは中村さんだけ

ベン図にしてみる

「=等しい」と「次のキーワードを含む」は直感的です。試しに関連レコードの支払方法フィールドに「paypay」を含む名簿を検索すると、下の図でAに該当する名簿を検索することができました。

中村さんはC

直感的ですね。続いて否定形を見ていきます。

関連レコードの「≠(等しくない)」と「次のキーワードを含まない」

一方で「含まない」条件を指定した場合、含まないレコードが1件でも関連レコードにあればその親レコードがヒットします。すべての関連レコードに対して「含まない」判定をした結果をORで結合した形です。

下の図でいうと赤い書類アイコンを探して、石原さん、山田さん、中村さんが三人とも該当します。

みんな該当

こうして図示してみるとよく分かりますね。

関連レコードを対象とした条件は、「=(等しい)」「含む」の真逆になるような集合を期待して「≠(等しくない)」「含まない」を使ってしまうと、期待と外れた動作をしてしまうことになります。

ベン図にしてみる

一方で「≠(等しくない)」と「次のキーワードを含まない」がクセモノでした。

「次のキーワードを含まない」という条件は、てっきり「次のキーワードを含む」レコードを全て除去した補集合になるとばかり思っていました。下の図でいうとBの緑の範囲を期待していました。

Bが欲しいけど実際は異なる結果になります

関連レコードではなく、通常の絞り込みでは「≠(等しくない)」と「キーワードを含まない」この図と同様の挙動になります。

ところが関連レコードを対象とした場合は「関連レコードのいずれかにpaypayを含まないレコードがあるレコード」の集合でした。

Bだけが欲しかったけど、得られたのは緑の範囲(B, C, E)

グループDとEが増えています。ややこしいですね。

「paypayを含まないレコード」が関連レコードのどこかに存在していれば、そのレコードは絞り込み条件に合致したことになります。

検証してみます

ここまで説明してきた挙動を検証してみたいと思います。みなさんのお手元ではわざわざダミーデータ作ったりしなくとも、手元の環境にそれっぽい修正を加えたら検証できるかと思います。よろしければお付き合いください。

ダミーデータを作る

まず支払記録的なアプリを作って空の状態でcsvをエクスポート。ChatGPTさんにダミーデータを作っていただきます。

ダミーの構築がホント手軽になりました

ダミーの作り方は過去記事で詳しく紹介しています。

1件だけ書き換える

ダミーデータをインポートしたら、その中から1件だけ支払方法をpaypayに書き換えてこんな集計ができるようにします。

中村さんが1回だけpaypayで支払ったかたちにします

1件だけ発生する仕分けがポイントです。

親側アプリを作って関連レコードを設定する

つぎに、支払いアプリを関連レコードで表示する顧客名簿的なアプリを作ります。

顧客名簿的なアプリには、関連レコードとして支払記録を表示できるようにしておきます。

顧客IDで関連させました

ここまでで準備完了です。

ではいよいよ検索を実行してみたいと思います。

親側アプリを検索してみる

顧客名簿的なアプリの一覧画面で、絞り込み条件を開いて関連レコードを条件に「=(等しい)」に「paypay」を指定します。

関連レコードの中にpaypayで支払った記録がある人だけを探します

すると、paypayの支払履歴を持つ中村俊介さんがヒットしました。最初のダミーデータ作成手順のときに書き換えた支払記録レコードですね。

paypayを含むので、そうですね。

次に「≠(等しくない)」に「paypay」を指定します。

ここが混乱した

ここで中村俊介さん以外の顧客が出てきて欲しいところですが、中村さんを含めた10人全員がヒットします。

これは「paypayと等しくないレコード」が関連レコードとして1件でも該当している顧客は全員ヒットしてしまうためです。もちろん中村俊介さんもヒットしてます。

全員ヒットした

ここまで説明してきた通りの動作が検証できました。

さきほどの図をもう一度表示します。Bに絞り込みたいのに、B, C, Eがヒットしている形です。

B, C, Eがヒットした

大分長々と説明してしまいました。

「~ない」という否定形の条件を指定した場合は、もしかしたら直感と異なる動きをするかもな、くらいの情報を片隅で覚えておいていただけたらと思います。

顧客が本当に欲しかった条件

Bが欲しいので、全体からACを取り除きます

顧客が本当に欲しかった条件はこちらです。(「≠(等しくない)」条件です)

import pandas as pd

df_payments = pd.read_csv('支払記録的なアプリのレコード.csv', encoding='ShiftJIS', dtype=str, na_filter=False)
df_customers = pd.read_csv('顧客名簿的なアプリのレコード.csv', encoding='ShiftJIS', dtype=str, na_filter=False)

df_paypay = df_payments[df_payments['支払種別'] == 'paypay']
# df_paypay = df_payments[df_payments['支払種別'].str.contains('paypay')]  # キーワードを含む場合はこちら
result = df_customers[df_customers['顧客ID'].isin(df_paypay['顧客ID'])]

# 結果をCSVとして出力
result.to_csv(output_path, encoding='UTF-8', index=False)  # type: ignore
print(f'output file: {output_path}')

すみません、kintoneだけでは無理でした…

えーっと、キン担ラボではpythonやTypeScriptを使った複雑な絞り込みのご依頼もお待ちしています!

タイトル画像について

有名なミーム『顧客が本当に欲しかったもの』にベン図を重ねた絵です。

いじってたらどこかで桜の木になってしまった

Wide vector illustration of a cherry blossom tree flourishing with pink blossoms. The swing, taking the form of a Venn diagram, dangles from a sturdy branch, set against a vast, clear blue sky. The scene is anchored by the caption: 'A peaceful place to relax and unwind' at the bottom.

プロンプト


いいなと思ったら応援しよう!