本ブログではGistにコード・スニペットを保存して、記事に貼り付けていることが多いのですが、コード・スニペットを対象とした検索ができなくて困っていました。
APEX 22.2では検索コンポーネントが新規に追加されています。これを使ってコード・スニペットを検索するアプリケーションを作ってみました。
https://apex.oracle.com/pls/apex/r/japancommunity/codesearch/home
検索コンポーネントについては、Oracle APEXのOffice Hourで開発者のCarsten Czarskiさんが解説しています。
Part 2: Marquee Features (APEX 22.2)
YouTubeの動画では、22分頃から解説が始まります。
https://www.youtube.com/watch?v=EEYLgNxx3Wo&t=1320s
今回のアプリケーションですが、クイックSQLの以下のモデルを使って表を作成します。
#prefix: cds
documents
title vc4000 /nn
url vc400
content clob
published date
updated date
attachments
post_id /fk documents
embedded_url vc400
embedded_content clob
raw_url vc400
raw_content clob
embedded_updated date
raw_updated date
ブログ記事の本文を保存する表CDS_DOCUMENTSに対して、複数のコード(添付ファイル)が表CDS_ATTACHMENTSとして紐づくという構造になっています。一般的によくある構造なので、応用はしやすいと思います。
以下より、アプリケーションを作成する手順を紹介します。
最初に上記のクイックSQLのモデルより、表CDS_DOCUMENTSとCDS_ATTACHMENTSを作成します。
SQLワークショップのユーティリティのクイックSQLを開き、左ペインにモデルを貼り付けます。その後SQLの生成、SQLスクリプトを保存、レビューおよび実行を順次クリックします。
表CDS_DOCUMENTSの列IDの型定義は以下に変更します。主キー制約の定義は変更しません。
参照制約が定義されているCDS_ATTACHMENTSの列POST_IDの型はvarchar2(32)に変更します。
以上の変更を行い、スクリプトを実行します。
アプリケーション作成ウィザードを、アプリケーション・ビルダーから起動します。
アプリケーションの名前はコード検索とします。テストに使用するデータを投入するための画面を、あらかじめアプリケーションに作成します。本題の検索画面は、アプリケーションを作成したのちに作成します。
ページの追加をクリックします。
ページの追加の追加ページを開き、複数のレポートを選択します。
表の選択画面が開きます。表CDS_DOCUMENTS、CDS_ATTACHMENTSを探してチェックを入れます。
ページの追加をクリックします。
それぞれの表について、フォーム付きの対話モード・レポートが追加されます。編集をクリックし、管理ページに切り替えます。
管理ページに変更すると、編集ボタンの横にあるアイコンがスパナに変わります。
AttachmentsとDocumentsの双方を管理ページに変更し、アプリケーションの作成を実行します。
以上でアプリケーションが作成されます。
アプリケーションを実行し管理画面を開くと、表CDS_DOCUMENTSとCDS_ATTACHMENTSの編集メニューが含まれていることが確認できます。テストに使うデータはこちらから登録できます。
apex.oracle.com上のアプリケーションではこの画面を使わずに、ブログ記事本文を表CDS_DOCUMENTSの列CONTENTに、Gistのスニペットを表CDS_ATTACHMENTSのRAW_CONTENTに投入しています。
表CDS_DOCUMENTSの列CONTENTおよびCDS_ATTACHMENTSの列RAW_CONTENTにOracle Textの全文検索索引を作成します。列CONTENTはレクサーとしてJAPANESE_LEXER、列RAW_CONTENTはコードなのでBASIC_LEXERを使用します。
あらかじめお断りしておきますが、最終的にOracle Text検索は使用しません。コード中のプロシージャ名やファンクション名の検索に向いていないためです。Oracle Textについては、一つの実装例としての紹介になります。
それぞれのレクサーのプレファレンスを、ja_lexerおよびbasic_lexerとして作成します。
begin
ctx_ddl.create_preference('ja_lexer', 'JAPANESE_LEXER');
ctx_ddl.create_preference('basic_lexer', 'BASIC_LEXER');
end;
/
表CDS_DOCUMENTSの列CONTENTに、Oracle Text索引CDS_DOCUMENTS_CTX1を作成します。
create index cds_documents_ctx1 on cds_documents(content)
indextype is ctxsys.context parameters('filter ctxsys.null_filter lexer ja_lexer sync(on commit)');
同様に表CDS_ATTACHMENTSの列RAW_CONTENTに、索引CDS_ATTACHMENTS_CTX1を作成します。
create index cds_attachments_ctx1 on cds_attachments(raw_content)
indextype is ctxsys.context parameters('filter ctxsys.null_filter lexer basic_lexer sync(on commit)');
以上で検索画面を作成する準備ができました。
共有コンポーネントの構成の検索を開きます。(英語だとSearch Configurationsで、これ以外は検索構成と訳されています。)
作成済みの検索構成が一覧されます。作成をクリックします。
検索構成の名前は本文検索 - Oracle Textとします。検索タイプとしてOracle Textを選択します。
次へ進みます。
ソースの表/ビューの名前として、CDS_DOCUMENTSを選択します。
次へ進みます。
主キー列はID(Varchar2)、Oracle Text索引列はCONTEXT(Clob)、タイトル列はTITLE(Varchar2)とします。アイコン・ソースとしてアイコン・クラスを選択し、アイコンCSSクラスとしてfa-file-text-oを指定します。
検索構成の作成をクリックします。
検索構成本文検索 - Oracle Textが作成されます。
設定の検索問合せ接頭辞にcontent-text、静的IDにcontent-textと設定します。列のマッピングのカスタム列1にURL(Varchar2)を選択します。
以上で変更の適用をクリックします。
名前はコード検索 - Oracle Textとします。検索タイプにOracle Textを選択します。
親となる表CDS_DOCUMENTSの列を検索結果に含めるため、ソースのソース・タイプとしてSQL問合せを選択し、以下のSQLをSQL SELECT文を入力に記述します。
select a.id, d.title, d.url, a.raw_url, a.raw_content
from cds_documents d join cds_attachments a
on d.id = a.post_id
主キー列はID(Number)、Oracle Text索引列はRAW_CONTENT(Clob)、タイトル列はTITLE(Varchar2)とします。アイコン・ソースとしてアイコン・クラスを選択し、アイコンCSSクラスとしてfa-file-text-oを指定します。
検索構成コード検索 - Oracle Textが作成されます。
設定の検索問合せ接頭辞にcode-text、静的IDにcode-textと設定します。列のマッピングのカスタム列1にURL(Varchar2)、カスタム列2にRAW_URL(Varchar2)を選択します。
以上で変更の適用をクリックします。
検索ページを作成します。このページをホームとするため、作成済みのホーム・ページを削除します。
ページ・デザイナでホーム・ページを開き、ページの削除を実行します。
ページが削除されたら、代わりになる検索ページを作成します。ページの作成を実行します。
検索ページを選択し、次へ進みます。
ページ番号は1、名前はコード検索とします。ページ・モードは標準です。
構成の検索としてコード検索 - Oracle Text、本文検索 - Oracle Textの双方をチェックします。
以上でページの作成をクリックします。
検索ページが作成されます。
今回はすべて公開されているデータを元にしているため、作成した検索ページの保護をすべて解除します。
識別の別名をhomeに変更します。
セキュリティの認証はパブリック・ページ、ディープ・リンクは有効、ページ・アクセス保護は制限なしとします。セッション管理のセッションを再結合はパブリック・セッションに対して有効に変更します。
変更を保存します。
検索ワードとしてapex_data_exportを入力します。
一件もヒットしません。
検索構成を変更するまえに、2つページの設定を変更します。
リージョン検索結果を選択し、プロパティ・エディタの属性を開きます。
デフォルトでは文字入力の都度、検索が実行されるようになっています。データベースへの負荷を減らすため、設定の入力時に検索をOFFに変更します。
続いて、検索結果として表示されるURLをクリックできるようにします。
設定のカスタム・レイアウトをONにし、結果行テンプレートに以下を書き込みます。
カスタム列1の置換文字列は&CUSTOM_01.、カスタム列2は&CUSTOM_02.です。これらのカスタム列が現れる部分をA要素に変更しています。
結果行テンプレートの記述方法は、結果行テンプレートのオンライン・ヘルプに記載されています。
以上の変更で、検索結果として表示されるURLがクリック可能になります。テンプレート・ディレクティブの使用もできるため、検索結果の見栄えの自由度は高いでしょう。
Oracle Textの検索はコード検索の要件に合わなかったため、検索構成を新規に作成します。
新たに作成する検索構成の名前は本文検索 - 標準とします。検索タイプは標準を選択します。これ以降の指定は、検索タイプがOracle Textのときと同じです。
列のマッピングのカスタム列1としてURL(Varchar2)を選択します。
同様に検索構成コード検索 - 標準を作成します。
作成された検索構成コード検索 - 標準の設定の検索問合せ接頭辞、静的IDはcodeとします。ソースの検索可能列としてRAW_CONTENT(Clob)を選択します。
列のマッピングのカスタム列1としてURL(Varchar2)を選択します。カスタム列2としてRAW_URL(Varchar2)を選択します。
以上で、置き換える検索構成が作成されました。
検索ページを開き、ソースの検索のコード検索 - Oracle Textを選択します。
識別の名前をコード検索、検索構成をコード検索 - 標準に変更します。
同様に本文検索 - Oracle Textの識別の名前を本文検索、検索構成を本文検索 - 標準に変更します。
以上でアプリケーションは完成です。
アプリケーションを実行して、apex_data_exportで検索してみます。
記事およびGistのスニペットの内容にapex_data_export(大文字小文字は無視されます)が含まれる記事が一覧されます。
検索構成に検索問合せ接頭辞が設定されています。本文検索 - 標準にはcontentが指定されているため、検索キーワードとしてcontent:apex_data_exportと入力するとブログ記事本文のみが検索対象になります。
この他にもいろいろな機能が、最初に紹介したYouTubeの動画で紹介されています。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/codesearch.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完