PowerCMS Xのサイト内全文検索機能(SearchEstraierプラグイン)で利用するHyper Estraierの属性検索演算子をAI(Claude Code)に作成してもらいました。
ちなみに、記事を執筆し読み返していると演算子名は「STRORINC」より「STRTOKENEQ」(トークン化 + 等価比較)の方が的確かなと思い始めました。
属性検索とは?
タイトル・カテゴリ・重要度など、本文以外のさまざまなデータをキーバリューのような形式で検索インデックスに格納しておき、検索に利用するものです。例えばcategory STREQ フルーツ
で検索すると、カテゴリに「フルーツ」が指定されている文書が抽出できます。詳細はUser's Guide of Hyper Estraier Version 1 (Japanese)をご覧ください。
遭遇した課題
以下のようなカテゴリ属性を持つ5つの文書があるとします。
# 文書1
categories=B787-8,Boeing
# 文書2
categories=777-300ER,Boeing
# 文書3
categories=A350-900,Airbus
# 文書4
categories=DHC8-Q400,Bombardier
# 文書5
categories=E170,EMBRAER
この時、Boeing
もしくはAirbus
が指定されている文書を抽出したいのですが、Hyper Estraierの既存の演算子…具体的にはSTRINC
やSTROREQ
では抽出できませんでした。
STRINC
はstrstr(tval, oval) != NULL
のように実装されており、単一の検索条件キーワードを部分一致で探しています。複数のキーワードを持つことは想定されていません。STROREQ
は検索条件に複数のキーワードを指定することができるのですが、属性値(検索対象)を複数持つことが想定されていません。属性値全体が検索条件のいずれかと完全一致することが必要です。
STRORINCの実装
先の課題を解決するために、検索条件も属性値もカンマ区切り(もしくはスペース区切り)で複数指定できるSTRORINC
があれば良いと考えました。ただ、Hyper EstraierはCで記述されているのでWeb制作のエンジニアである私には改変が難しいです。estraier.cファイルに検索処理が書かれており、文字列の一致を確かめるような実装であることは理解できたので、Claude Codeに分析と実装を依頼しました。
> est_check_stroreq を参考に STRORINC を作成したい。
`tval = "B787-8,Boeing"` 、`oval = "Boeing,Airbus"`でヒットさせたい。
簡易なプロンプトでしたが、Claude CodeがIDEと連携してestraier.cファイルを直接参照できたため、既存の実装パターンを理解して適切な実装を行ってくれました。具体的にはest_check_stroreq
の実装を分析し、それをベースに新しい演算子の仕様を満たすest_check_strorinc
を作成してくれました。
⏺ Update Todos
⎿ ☐ Find a good location to add the STRORINC function declaration
☐ Add the STRORINC function declaration near est_check_stroreq
☐ Implement the est_check_strorinc function
☐ Find where STROREQ is used and add STRORINC support
☐ Test the implementation
(中略)
⏺ STRORINCの実装が完了しました。
実装内容:
1. estraier.h に ESTOPSTRORINC マクロを追加
2. estraier.c に:
- est_check_strorinc 関数の宣言と実装を追加
- STROREQ と同様の処理箇所に STRORINC のサポートを追加
est_check_strorinc関数は、tval内の各トークン(カンマまたはスペース区切り)がoval内のいずれか
のトークンと完全一致するかをチェックします。
⏺ テストケースを追加して、STRORINCが正しく動作することを確認しましょう。引っかかる場合と引っか
からない場合の両方をテストします。
⏺ Write(test_strorinc.c)
⎿ Wrote 151 lines to test_strorinc.c
#include
#include
#include
static int est_check_strorinc(const char *tval, const char *oval){
const char *tsp, *tep, *osp, *oep, *trp, *orp;
assert(tval && oval);
tsp = tval;
while(*tsp != '\0'){
while(*tsp == ' ' || *tsp == ','){
… +141 lines (ctrl+r to expand)
⏺ Bash(gcc -o test_strorinc test_strorinc.c && ./test_strorinc)
⎿ === STRORINC Test Cases ===
【ヒットするケース】
… +37 lines (ctrl+r to expand)
⏺ 完璧です!すべてのテストケースが期待通りに動作しています。
テスト結果のまとめ:
ヒットするケース ✓
- 完全一致のトークンがある場合
- 位置に関係なく(最初、中間、最後)一致
- スペース区切り、カンマ区切り、混合でも動作
- 特殊文字や日本語でも正常動作
ヒットしないケース ✓
- 部分一致だけでは不十分(完全一致が必要)
- 空文字列の適切な処理
- 前方・後方の部分一致では検出されない
STRORINCは「tval内のいずれかのトークンがoval内のいずれかのトークンと完全一致」という条件で正
しく動作しています。
仕様
- 属性値を単語単位で分割
- 検索条件の各キーワードと完全一致チェック
- いずれかのキーワードと一致すればマッチ
既存演算子との比較
演算子 | 属性値の扱い | 検索条件 | 例での結果 |
---|---|---|---|
STRINC | 全体を1つの文字列として扱う | 単一キーワード(部分一致) | 使用不可 |
STROREQ | 全体を1つの文字列として扱う | 複数キーワード可(完全一致) | ヒットなし |
STRORINC | トークンに分割 | 複数キーワード可(トークン単位で完全一致) | 文書1,2,3がヒット |
インストール
改良前のHyper Estraier同様、makeしてインストールするだけです。
検索実行例
bash-5.2# estcmd search -va -attr 'categories STRORINC Boeing Airbus' casket
--------[7365852B3E327430]--------
VERSION 1.0
NODE local
HIT 3
HINT#1 [UVSET] 6
TIME 0.000438
DOCNUM 6
WORDNUM 14
VIEW ATTRIBUTE
--------[7365852B3E327430]--------
@id=1
@title=B787-8
@uri=https://www.example.jp/test1.html
categories=B787-8,Boeing
--------[7365852B3E327430]--------
@id=2
@title=Boeing 777-300ER
@uri=https://www.example.jp/test2.html
categories=777-300ER,Boeing
--------[7365852B3E327430]--------
@id=3
@title=Airbus A350-900
@uri=https://www.example.jp/test3.html
categories=A350-900,Airbus
--------[7365852B3E327430]--------:END
PowerCMS Xのタグを利用して検索条件を指定すると、以下のような記述になります。
<mt:estraiersearch add_attr="categories" add_condition="STRORINC" value="Boeing Airbus">
/* 検索結果一覧表示HTML */
</mt:estraiersearch>
まとめ
生成AIの活用により、今まではどうにもできなかったHyper Estraierへの機能追加を行うことができ、PowerCMS Xのサイト内全文検索機能を強化することができました。今後もClaude CodeやCursor等の生成AIを上手く活用していきたいです。