検索辞書
検索辞書を使用すると、社内の俗称や型番の表記ゆれを検索に登録できます。例えば社内で「経費くん」と呼ばれている「経費精算システム」の記事を、どちらの名前で検索しても返せます。コンテンツ本文に俗称を書き足す必要はありません。
検索辞書は以下の機能を提供します。
- 同義語による検索クエリの言い換え
- 用語の解説を検索結果に返す
- プロジェクト全体の語彙管理(テーブルごとの設定は不要)
- エントリを削除せずに一時的に無効化
検索辞書が使えるのは、セマンティック検索
を有効にしたプロジェクトで mode に semantic または hybrid
を指定した検索だけです。keyword
の検索には影響しません。利用中の環境でセマンティック検索を使えるかどうかは管理者に確認してください。システム側で無効な環境では、エントリの登録・更新は成功しても検索には反映されません。
ユースケース例
社内の俗称や略称で検索できるようにする
製品名や部署名には、正式名称のほかに現場でしか使われない呼び方があります。正式名称を見出し語、俗称を同義語として登録すると、どちらで検索しても同じコンテンツに当たります。
型番の表記ゆれを吸収する
全角と半角やハイフンの種類の違いは、表記の同一視 で自動的に吸収されます。EX 1200X のように語の途中に空白が入る表記や、「イーエックス1200」のように別の呼び方は吸収されないため、同義語として登録します。
用語集として検索結果に出す
説明を付けて登録したエントリは、それ自体が検索対象になります。編集者が社内用語で検索したときに、コンテンツの一覧と一緒に用語の解説を出せます。
前提
検索辞書はプロジェクト単位の語彙で、テーブルごとの設定はありません。ただし辞書が使われるのは semantic / hybrid で検索できるテーブルだけです。orizm.config.ts でセマンティック検索を有効にし、対象の列を指定してください(有効化と対象の列)。
import { defineConfig } from "@orizm/cli/config";
export default defineConfig({
semanticSearch: { enabled: true },
tables: {
blog: {
columns: {
title: { type: "string", required: true, semanticSearch: true },
body: { type: "string", required: true, semanticSearch: true },
},
enableSearch: true,
},
},
});検索辞書の操作は CMS SDK と Management API で行います。Orizm Console と Project Console に検索辞書の画面はありません。
2 つの働き
検索辞書は 2 つの形で検索に使われます。エントリの内容によって、どちらが使われるかが決まります。
| 働き | 使われる条件 | 反映タイミング |
|---|---|---|
| 同義語によるクエリの言い換え | hybrid 検索。同義語が 1 つ以上あるエントリ | 即時 |
| 用語の解説を検索結果に返す | CMS SDK の semantic / hybrid 検索。説明があるエントリ | 非同期 |
enabled: false のエントリはどちらにも使われません。
同義語によるクエリの言い換え
hybrid で検索すると、クエリに辞書の表記が含まれる場合に、同じエントリの別表記へ置き換えたクエリが検索に足されます。置き換えは見出し語と同義語の双方向です。例えば見出し語「経費精算システム」と同義語「経費くん」を登録すると、「経費くんの使い方」というクエリからは「経費精算システムの使い方」が足されます。
元のクエリは必ず残るため、辞書を登録して一致しなくなるコンテンツはありません。ただし言い換えで新しく一致したコンテンツが加わる分、既存のヒットの順位は下がります。一致の多いクエリでは、既存のヒットが結果に表示されなくなることがあります。
この言い換えは Consumer SDK の hybrid 検索でも同じように使われます。どのエントリが使われたかは検索結果に現れません。埋め込みの処理が失敗して keyword と同じ結果に切り替わったときは、言い換えも使われません。
一致はクエリ文字列に対する部分一致です。日本語は単語の区切りを見ないため、「冷却ユニットの価格」の中の「冷却ユニット」に一致します。表記の端が英字なら英字と隣り合わない位置に、数字なら数字と隣り合わない位置にだけ一致します。go は google
の中では一致しませんが、iphone15 の中の iphone には一致します。
1 つの足されるクエリで置き換えるのは 1 エントリの 1 表記だけです。クエリの中の 2 語がどちらも別表記で書かれているコンテンツは拾えないことがあります。
1 回の検索で足されるクエリは最大 20 件です。言い換えに使われるのは、同義語を持つ有効なエントリのうち登録が古い順に 5,000 件までです。
用語の解説を検索結果に返す
説明(description)を付けたエントリは、それ自体が検索対象になります。CMS SDK で semantic または hybrid の検索をすると、検索結果に _dictionary が付きます。クエリと近い順に最大 3 件の解説が返ります。
const result = await cmsClient.tables.blog.search({
query: "出張の立替を申請する",
mode: "hybrid",
});
console.log(result.contents); // コンテンツのヒット
console.log(result._dictionary); // 辞書のヒット(最大 3 件)_dictionary の各要素は以下のフィールドを持ちます。
| フィールド | 説明 |
|---|---|
id | エントリの ID。get() / update() / delete() にそのまま渡せます |
term | 見出し語(登録した表記のまま) |
description | 説明 |
score | クエリとの近さ。行の _semantic.score とは尺度が違うため比較できません |
近さの判定には説明だけでなく見出し語と同義語も使われるため、説明に俗称を書かなくても俗称で検索したときに当たります。
辞書のヒットは contents とは別の枠で返り、totalCount には含まれません。ページングもしません。クエリと関連の薄いエントリは返らないため、説明付きのエントリが 3 件以上あっても 0〜2 件になることがあります。返ってきたものをさらに絞りたい場合は score で判断してください。
_dictionary は状態によって 3 通りになります。
- キーが無い: 次のいずれかです。
keyword検索。keywordと同じ結果に切り替わったとき。説明付きの有効なエントリが 1 つも無いプロジェクト(反映待ちの間を含む)。辞書の検索が一時的に失敗したとき。どのテーブルも読めないキーでの検索 - 空配列: 辞書は引けたが、クエリに近いエントリが無かった
- 配列: ヒットあり
_dictionary は常に省略され得るものとして扱ってください。
辞書のヒットにはグループによる権限のフィルタが掛かりません。特定のグループにだけ見せたい情報は説明に書かないでください。
Consumer SDK の検索には _dictionary は付きません。辞書エントリには公開と下書きの区別が無いためです。
表記の同一視
エントリは見出し語を正規化した値で識別されます。表記が違っても正規化後に同じなら同じエントリで、検索時の一致にも同じ正規化が使われます。以下の違いは同じ語として扱われます。
- 全角と半角(
EX-1200X=ex-1200x) - 大文字と小文字
- 半角カナと全角カナ
- ハイフン・マイナス・ダッシュ類
- 前後の空白、連続する空白、全角空白
- 貼り付けで紛れ込む不可視文字(ゼロ幅スペースなど)
長音記号 ー はハイフンとは別の文字です。コーヒー と コ-ヒ- は別の語になります。
見出し語と同義語は入力した表記のまま保存・返却されます。前後の空白は取り除き、タブ・改行・連続する空白は空白 1 つにまとめます。正規化すると見出し語や先に指定した同義語と同じになる同義語は、登録時に取り除かれます。
使い方
CMS SDK の cmsClient.dictionary から操作します。テーブルの配下ではなくクライアント直下にあります。
登録・更新・削除には、プロジェクト内のいずれかのテーブルへの書き込み権限が必要です。一覧と取得には、いずれかのテーブルへの読み取り権限が必要です。権限が無いロールでは 403 になります(権限)。
エントリの登録
add() に登録したいエントリの配列を渡します。1 回のリクエストで複数のエントリを登録できます。
await cmsClient.dictionary.add([
{
term: "経費精算システム",
synonyms: ["経費くん", "経費システム"],
description: "出張費や備品代の立替を申請・承認する社内システム。",
},
]);description と synonyms は省略できます。enabled を false にすると、登録はしても検索には使われない状態で作れます。既定は true です。
add() は、正規化した見出し語が既存のエントリと一致した場合、そのエントリを丸ごと置き換えます。渡さなかったフィールドは初期値(synonyms は []、description は null、enabled は true)に戻ります。一部のフィールドだけを変えたいときは update() を使ってください。
置き換えになるため、同じ一覧を投入し直しても重複したエントリは作られず、ID も変わりません。1 回のリクエストに同じ見出し語を 2 つ入れるとエラーになります。
エントリの一覧取得
list() でエントリの一覧を取得します。登録が古い順に返り、enabled: false のエントリも含まれます。
const { contents, totalCount } = await cmsClient.dictionary.list();query で絞り込み、limit と offset でページングできます。
await cmsClient.dictionary.list({ query: "経費", limit: 50, offset: 0 });query は見出し語には部分一致、同義語には完全一致で当たります。どちらも正規化して比べるため、半角で登録した語を全角で検索できます。正規化して空になる値は未指定と同じ扱いです。limit を指定しない場合は 100 件まで取得されます。
エントリの取得
get() に ID を渡して 1 件を取得します。
const entry = await cmsClient.dictionary.get(entryId);エントリの部分更新
update() は渡したフィールドだけを変更します。
await cmsClient.dictionary.update(entryId, {
synonyms: ["経費くん", "経費システム", "精算システム"],
});description に null を渡すと説明を消せます。説明が無くなったエントリは検索結果に返らなくなりますが、同義語による言い換えは引き続き使われます。
await cmsClient.dictionary.update(entryId, { description: null });一時的に止めたいときは enabled を false にします。削除せずに両方の働きを止められます。
await cmsClient.dictionary.update(entryId, { enabled: false });term を変えると、エントリを識別する値も一緒に変わります。変更後の表記が既にある別のエントリと同じになる場合はエラーになります。新しい見出し語と同じになる同義語は取り除かれます。
エントリの削除
delete() に ID を渡します。
await cmsClient.dictionary.delete(entryId);検索への反映タイミング
同義語による言い換えは、登録・更新した直後の検索から使われます。
用語の解説の検索対象化(_dictionary)は非同期です。エントリを変更すると辞書の索引が作り直され、それが終わってから検索結果に現れます。所要時間は説明付きのエントリの件数によって変わります。無効化や削除で検索結果から消える場合も同じです。説明付きの有効なエントリが 1 つも無くなると、以降の検索では _dictionary が付かなくなります。
上限値
| 対象 | 上限 |
|---|---|
1 回の add() で登録できるエントリ数 | 500 件(1 件以上) |
| 見出し語・同義語 1 つあたりの文字数 | 200 文字 |
| 1 エントリの同義語の数 | 50 個 |
| 説明の文字数 | 2000 文字 |
list() の limit | 500(既定 100) |
見出し語・同義語・説明には、タブ・改行・復帰以外の制御文字を含められません。説明は複数行で登録できます。空白だけの値は登録できません。
監査ログ
エントリの登録・更新・削除は 監査ログ に記録されます。