kintacoです。自社の重複有無・サジェスト表示プラグインでは、候補比較にNFKC正規化を使っています。この記事では実コードのnormal関数と同じ処理を使い、前方一致・部分一致・正規化後の重複除外に絞って解説します。
サンプルは配列を受け取って候補を返す純粋関数です。kintoneへのAPI照会、入力欄のDOM操作、候補の選択・入力は含みません。製品版にある編集距離による類似候補も省いています。
元の表記と、比較用の文字列を分ける
表示用の値を正規化後の文字列に置き換えるのではなく、比較に使うキーだけを作ります。「ABC 商事」と「abc商事」は同じキーになりますが、候補の表示文字列は最初の値を保持します。
function normal(value) {
return String(value).normalize('NFKC').toLocaleLowerCase('ja').replace(/\s+/g, '');
}
function suggest(input, items, limit = 5) {
if (!Number.isInteger(limit) || limit < 1 || limit > 20) {
throw new Error('limitは1~20の整数にしてください。');
}
const term = normal(input);
if (!term) return [];
const seen = new Set();
const ranked = [];
items.forEach((item, index) => {
if (typeof item !== 'string') return;
const key = normal(item);
if (!key || key === term || seen.has(key)) return;
const score = key.startsWith(term) ? 0 : key.includes(term) ? 1 : -1;
if (score < 0) return;
seen.add(key);
ranked.push({item, score, index});
});
return ranked.sort((a, b) => a.score - b.score || a.index - b.index)
.slice(0, limit).map(row => row.item);
}
この順番にする理由
空欄は候補検索しません。次に、入力自体と同じ候補は除きます。そのあと前方一致を先、部分一致を後として並べ、同じ比較キーを持つ候補は一度だけ採用します。
候補内にHTMLらしい文字列があっても、この関数は文字列として返すだけです。画面へ表示する場合はtextContentなどを使い、innerHTMLへ未検証の値を流し込まないでください。
NFKCで解決しないこと
NFKCは意味を理解する処理ではありません。「株式会社」と「(株)」、旧社名と新社名、カナの読み、翻訳語を同義語へ変換するわけではありません。また、空白をすべて除くと、業務によっては別の名前を同一候補として扱ってしまいます。空白や大小文字を区別すべき識別子には、そのまま使わないでください。
候補の整理と重複禁止は別の機能
この関数はブラウザーに渡された候補配列しか見ません。候補が出ないことを「同じデータが存在しない」根拠にしてはいけません。API取得件数の上限、閲覧権限、取得後に登録されたデータも考慮します。
保存時の同時登録まで防ぎたい場合には、標準の重複禁止設定などを別途検討します。製品版の重複表示も警告であり、保存を禁止する機能ではありません。
確認する入力例
console.log(suggest('abc', ['ABC商事', 'abc 商事', '東京ABC', 'abc']));
// ['ABC商事', '東京ABC']
正規化・完全一致除外・重複除外・順位・件数制限をNode.jsで確認しました。kintoneの実画面へ組み込んだ動作テストは含みません。日本語IME変換中に照会しない、古い非同期応答を破棄するなどの処理は、UIに接続する段階で必要になります。
設定画面付きの入力支援が必要な場合
自社の重複有無・サジェスト表示プラグインの仕様・設定画面で、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。
無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。
参考資料
製品仕様と実コードの確認元:DuplicateSuggest/src/js/core.js(1.0.4)。