6.1 問合せの概要
Oracle Textの基本的な問合せでは、問合せ式を入力します。式は、通常はワードで、演算子を併用する場合と併用しない場合があります。式を満たすすべてのドキュメント(事前に索引付け済)が、各ドキュメントの関連性スコアとともに戻ります。スコアを使用して、結果セット内のドキュメントを順序付けできます。
Oracle Textの問合せを入力するには、SQLのSELECT
文を使用します。索引のタイプに応じて、WHERE
句にCONTAINS
演算子またはCATSEARCH
演算子のいずれかを使用します。これらの演算子は、PL/SQLカーソル内など、SELECT
文を使用できる状況であれば、いつでもプログラムで使用できます。
CTXRULE
索引を使用してドキュメントを分類するには、MATCHES
演算子を使用します。
6.1.1 CONTAINSによる問合せ
CONTEXT
索引タイプを作成する場合は、CONTAINS
演算子を使用して問合せを入力する必要があります。この索引は、大量のまとまったドキュメントのコレクションを索引付けする場合に適しています。
CONTAINS
演算子では、複数の演算子を使用して検索条件を定義できます。これらの演算子によって、論理、近接、ファジー、ステミング、シソーラスおよびワイルドカードの各検索を入力できます。また、適切に構成された索引を使用すると、HTMLやXMLのような内部構造を持つドキュメントに対してセクション検索を入力することもできます。
CONTAINS
では、ABOUT
演算子を使用して、ドキュメント・テーマを検索できます。
6.1.1.1 CONTAINS SQL例
SELECT
文では、CONTAINS
演算子を使用してWHERE
句で問合せを指定します。また、ヒットリストのヒットごとにスコアを戻すには、SCORE
演算子を指定します。次の例では、問合せの入力方法を示します。
SELECT SCORE(1), title from news WHERE CONTAINS(text, 'oracle', 1) > 0;
次のように、ORDER
BY
句を使用して、結果を最も高いスコアのドキュメントから最も低いスコアのドキュメントに順序付けることができます。
SELECT SCORE(1), title from news WHERE CONTAINS(text, 'oracle', 1) > 0 ORDER BY SCORE(1) DESC;
CONTAINS
演算子の後には、> 0構文が必要です。この構文は、CONTAINS
演算子によって戻されるスコアの値が、戻される行に対してゼロより大きい必要があることを指定します。
SELECT
文でSCORE
演算子がコールされた場合、CONTAINS
演算子は、前述の例に示すように、3番目のパラメータでスコア・ラベルの値を参照する必要があります。
6.1.1.2 CONTAINS PL/SQL例
PL/SQLアプリケーションでは、カーソルを使用して問合せ結果をフェッチできます。
次の例では、CONTAINS
問合せをNEWS
表に対して入力し、ワードoracleを含むすべての記事を検索します。ヒットしたもののうち上位10個のタイトルとスコアが出力されます。
declare rowno number := 0; begin for c1 in (SELECT SCORE(1) score, title FROM news WHERE CONTAINS(text, 'oracle', 1) > 0 ORDER BY SCORE(1) DESC) loop rowno := rowno + 1; dbms_output.put_line(c1.title||': '||c1.score); exit when rowno = 10; end loop; end;
この例では、カーソルFOR
ループを使用して、ヒットしたもののうち上位10個を取り出します。SCORE
演算子の戻り値に対して、別名scoreが宣言されています。スコアとタイトルがカーソル・ドット表記法を使用して出力として表示されます。
6.1.1.3 CONTAINSによる構造化問合せの例
構造化問合せは複合問合せとも呼ばれ、テキスト列を問い合せる1つのCONTAINS
述語と、構造化データ列を問い合せる別の述語を持つ問合せです。
構造化問合せを入力するには、SELECT
文のWHERE
条件に構造化句を指定します。
たとえば、次のSELECT
文は、1997年10月1日以降に書かれた、ワードoracleを含む記事をすべて検索します。
SELECT SCORE(1), title, issue_date from news WHERE CONTAINS(text, 'oracle', 1) > 0 AND issue_date >= ('01-OCT-97') ORDER BY SCORE(1) DESC;
6.1.2 CATSEARCHによる問合せ
CTXCAT
索引タイプを作成する場合は、CATSEARCH
演算子を使用して問合せを入力する必要があります。
この索引は、使用しているアプリケーションで、テキスト列に短いテキスト断片を格納し、関連列に関連情報を格納する場合に適しています。
たとえば、オンライン・オークション・サイトを提供しているアプリケーションの場合、表のテキスト列に品目の説明を格納し、その他の列に日付と価格情報を格納するという具合です。CTXCAT
索引を使用すると、1つ以上の列にBツリー索引を作成できるため、複雑な問合せに対する問合せのパフォーマンスが通常高速になります。
CATSEARCH
による問合せに使用できる演算子は、AND
やORなどの論理操作に制限されています。
構造化基準を定義するには、>、<、=、BETWEEN
およびIN
演算子を使用します。
ノート:
Oracle Textの索引タイプCTXCAT
は、Oracle Database 23aiでは非推奨です。索引タイプ自体とその演算子CTXCAT
は、将来のリリースで削除される可能性があります。CONTEXT
問合せの代替文法としてCTXCAT
およびCTXCAT
文法の使用はどちらも非推奨です。かわりに、Oracleでは、CONTEXT
索引タイプを使用することをお薦めします。索引タイプは、トランザクション以外のすべての同じ機能を提供できます。CONTEXT
でのトランザクションに近い動作は、SYNC(ON COMMIT)
または短い期間(できればSYNC(EVERY [time-period])
)を使用して実現できます。
CTXCAT
は、通常、索引のサイズが数メガバイトのときに導入されました。最近の大規模な索引は、CTXCAT
で管理が困難な場合があります。CTXCAT
への索引セットの追加は、CONTEXT
索引タイプでFILTER BY
列とORDER BY
列、またはSDATA
列(あるいはその両方)を使用することで、より効率的に実行できます。したがって、CTXCAT
が適切な選択になることはほとんどありません。Oracleでは、より効率的なCONTEXT
索引タイプを選択することをお薦めします。
6.1.2.1 CATSEARCH SQL問合せの例
CATSEARCH
による一般的な問合せの例として、ワードcameraを含むすべての行を検索してbid_close
の日付順にソートする次の構造化句などがあります。
SELECT FROM auction WHERE CATSEARCH(title, 'camera', 'order by bid_close desc')> 0;
入力できる構造化問合せのタイプは、サブ索引の作成方法によって異なります。
関連項目:
前述の例のように、CATSEARCH
問合せの構造化部分を指定するには、3番目のstructured_query
パラメータを使用します。構造化式の列には、対応するサブ索引が必要です。
たとえば、category_id
とbid_close
には、AUCTION
表のctxcat
索引内にサブ索引があるとします。この場合は、次のような構造化問合せを入力します。
SELECT FROM auction WHERE CATSEARCH(title, 'camera', 'category_id=99 order by bid_close desc')> 0;
6.1.2.2 CATSEARCH例
次の例は、CTXCAT
索引に対するフィールド・セクション検索を示しています。これは、CATSEARCH
問合せの問合せテンプレートでCONTEXT
構文を使用します。
-- Create and populate table create table BOOKS (ID number, INFO varchar2(200), PUBDATE DATE); insert into BOOKS values(1, '<author>NOAM CHOMSKY</author><subject>CIVIL RIGHTS</subject><language>ENGLISH</language><publisher>MIT PRESS</publisher>', '01-NOV-2003'); insert into BOOKS values(2, '<author>NICANOR PARRA</author><subject>POEMS AND ANTIPOEMS</subject><language>SPANISH</language> <publisher>VASQUEZ</publisher>', '01-JAN-2001'); insert into BOOKS values(1, '<author>LUC SANTE</author><subject>XML DATABASE</subject><language>FRENCH</language><publisher>FREE PRESS</publisher>', '15-MAY-2002'); commit;
-- Create index set and section group exec ctx_ddl.create_index_set('BOOK_INDEX_SET'); exec ctx_ddl.add_index('BOOK_INDEX_SET','PUBDATE'); exec ctx_ddl.create_section_group('BOOK_SECTION_GROUP', 'BASIC_SECTION_GROUP'); exec ctx_ddl.add_field_section('BOOK_SECTION_GROUP','AUTHOR','AUTHOR'); exec ctx_ddl.add_field_section('BOOK_SECTION_GROUP','SUBJECT','SUBJECT'); exec ctx_ddl.add_field_section('BOOK_SECTION_GROUP','LANGUAGE','LANGUAGE'); exec ctx_ddl.add_field_section('BOOK_SECTION_GROUP','PUBLISHER','PUBLISHER'); -- Create index create index books_index on books(info) indextype is ctxsys.ctxcat parameters('index set book_index_set section group book_section_group'); -- Use the index -- Note that: even though CTXCAT index can be created with field sections, it -- cannot be accessed using CTXCAT grammar (default for CATSEARCH). -- We need to use query template with CONTEXT grammar to access field -- sections with CATSEARCH select id, info from books where catsearch(info, '<query> <textquery grammar="context"> NOAM within author and english within language </textquery> </query>', 'order by pubdate')>0;
6.1.3 MATCHESによる問合せ
CTXRULE
索引タイプを作成する場合は、MATCHES
演算子を使用してドキュメントを分類する必要があります。CTXRULE
索引は、本来は分類を定義する問合せのセットに作成される索引です。
たとえば、ドキュメントの着信ストリームをドキュメントの内容に基づいて分類する必要がある場合は、カテゴリを定義する問合せのセットを作成できます。この問合せは、テキスト列の行として作成します。このタイプの表を作成するには、CTX_CLS.TRAIN
プロシージャを使用します。
次に、CTXRULE
索引を作成するために表を索引付けします。ドキュメントの着信時に、MATCHES
演算子を使用して各ドキュメントを分類します。
関連項目:
6.1.3.1 MATCHES SQL問合せ
MATCHES
問合せでは、指定したドキュメントに一致する問合せ表内のすべての行を検索します。querytable
表がCTXRULE
索引に関連付けられている場合、次の問合せを入力します。
SELECT classification FROM querytable WHERE MATCHES(query_string,:doc_text) > 0;
:doc_text
バインド変数には、分類されるCLOB
ドキュメントが含まれています。
次に、その単純な例を示します。
create table queries ( query_id number, query_string varchar2(80) ); insert into queries values (1, 'oracle'); insert into queries values (2, 'larry or ellison'); insert into queries values (3, 'oracle and text'); insert into queries values (4, 'market share'); create index queryx on queries(query_string) indextype is ctxsys.ctxrule; select query_id from queries where matches(query_string, 'Oracle announced that its market share in databases increased over the last year.')>0
この問合せでは、問合せ1 (ドキュメントにoracleというワードが出現)および4 (ドキュメントにmarket shareという句が出現)が返され、問合せ2 (larryおよびellisonというワードは出現しない)および3 (ドキュメント内にテキストがないため問合せに一致しない)は返されません。
この例では、簡略化するために、ドキュメントを文字列として渡しています。通常、ドキュメントはバインド変数で渡されます。
MATCHES
問合せでは、VARCHAR2
またはCLOBのドキュメント・テキストを使用できます。
BLOB
入力は使用できないため、フィルタ処理済のドキュメントに直接一致させることはできません。かわりに、AUTO_FILTER
フィルタを使用してバイナリ・コンテンツをCLOB
にフィルタ処理する必要があります。この例では、2つのことを想定しています。
-
ドキュメント・データは、
:doc_blob
バインド変数にあります。 -
CTX_DOC.POLICY_FILTER
で使用できるmy_policy
をすでに定義しています。
たとえば:
declare doc_text clob; begin -- create a temporary CLOB to hold the document text doc_text := dbms_lob.createtemporary(doc_text, TRUE, DBMS_LOB.SESSION); -- create a simple policy for this example ctx_ddl.create_preference(preference_name => 'fast_filter', object_name => 'AUTO_FILTER'); ctx_ddl.set_attribute(preference_name => 'fast_filter', attribute_name => 'OUTPUT_FORMATTING', attribute_value => 'FALSE'); ctx_ddl.create_policy(policy_name => 'my_policy', filter => 'fast_filter); -- call ctx_doc.policy_filter to filter the BLOB to CLOB data ctx_doc.policy_filter('my_policy', :doc_blob, doc_text, FALSE); -- now do the matches query using the CLOB version for c1 in (select * from queries where matches(query_string, doc_text)>0) loop -- do what you need to do here end loop; dbms_lob.freetemporary(doc_text); end;
テキストをCLOB
に取り込んでMATCHES
問合せを入力する必要があるため、CTX_DOC.POLICY_FILTER
プロシージャによりBLOB
をCLOB
データにフィルタ処理します。これは、CTX_DDL.CREATE_POLICY
を使用してすでに作成されたポリシーの名前を1つの引数として受け取ります。
関連項目:
CTX_DOC.POLICY_FILTER
の詳細は、『Oracle Textリファレンス』を参照してください
ファイルがデータベース文字セット内のテキストである場合、BFILE
を作成し、DBMS_LOB.LOADFROMFILE
ファンクションを使用してCLOB
にロードするか、UTL_FILE
を使用して、ファイルを一時的なCLOB
ロケータに読み込むことができます。
ファイルがAUTO_FILTER
フィルタ処理を必要とする場合は、ファイルをBLOB
にロードして、前述のように、CTX_DOC.POLICY_FILTER
をコールします。
関連項目:
拡張された分類の例は、「Oracle Textでのドキュメントの分類」を参照してください
6.1.3.2 MATCHES PL/SQL例
次の例では、問合せのプロファイル表が
CTXRULE
索引に関連付けられていることを前提としています。また、newsfeed
表に分類対象の記事のセットが含まれていることも前提となります。
この例では、newsfeed
表内をループし、MATCHES
演算子を使用して各記事を分類します。結果は、results
表に格納されます。
PROMPT Populate the category table based on newsfeed articles PROMPT set serveroutput on; declare mypk number; mytitle varchar2(1000); myarticles clob; mycategory varchar2(100); cursor doccur is select pk,title,articles from newsfeed; cursor mycur is select category from profiles where matches(rule, myarticles)>0; cursor rescur is select category, pk, title from results order by category,pk; begin dbms_output.enable(1000000); open doccur; loop fetch doccur into mypk, mytitle, myarticles; exit when doccur%notfound; open mycur; loop fetch mycur into mycategory; exit when mycur%notfound; insert into results values(mycategory, mypk, mytitle); end loop; close mycur; commit; end loop; close doccur; commit; end;
次の例では、分類された記事をカテゴリ別に表示します。
PROMPT display the list of articles for every category PROMPT set serveroutput on; declare mypk number; mytitle varchar2(1000); mycategory varchar2(100); cursor catcur is select category from profiles order by category; cursor rescur is select pk, title from results where category=mycategory order by pk; begin dbms_output.enable(1000000); open catcur; loop fetch catcur into mycategory; exit when catcur%notfound; dbms_output.put_line('********** CATEGORY: '||mycategory||' *************'); open rescur; loop fetch rescur into mypk, mytitle; exit when rescur%notfound; dbms_output.put_line('** ('||mypk||'). '||mytitle); end loop; close rescur; dbms_output.put_line('**'); dbms_output.put_line('*******************************************************'); end loop; close catcur; end;
関連項目:
拡張された分類の例は、「Oracle Textでのドキュメントの分類」を参照してください
6.1.4 ワード問合せと句問合せ
ワード問合せは、ワードまたは句に対する問合せです。たとえば、テキスト表でワードdogを含むすべての行を検索するには、問合せ語句として、dogを指定して問合せを入力します。
ワード問合せは、SQL演算子のCONTAINS
とCATSEARCH
の両方で入力できます。ただし、句問合せは、異なる方法で解釈されます。
-
CONTAINS句問合せ: 問合せ式に複数のワードが空白のみ(演算子なし)で区切られて含まれている場合、そのワードの文字列は句とみなされます。Oracle Textでは、問合せ中に文字列全体が検索されます。たとえば、句international lawを含むすべてのドキュメントを検索するには、句international lawを指定して問合せを入力します。
-
CATSEARCH句問合せ:
CATSEARCH
演算子では、句のワード間にAND
演算子を挿入します。たとえば、international lawの問合せでは、international AND lawとして解釈されます。
6.1.5 ストップワードの問合せ
ストップワードは、索引エントリが作成されないワードです。これは、通常、検索の対象とならない、その言語の一般的なワードです。
Oracle Textには、使用言語のデフォルトのストップワード・リストが組み込まれています。このリストは、ストップリストと呼ばれます。たとえば、英語では、ワードthisおよびthatは、デフォルトのストップリストでストップワードとして定義されています。このデフォルトのストップリストを変更したり、CTX_DDL
パッケージを使用して新しいストップリストを作成できます。また、索引を作成した後で、ALTER INDEX
文でストップワードを追加することもできます。
ストップワードまたはストップワードのみで構成されている句に対する問合せは発行できません。たとえば、thisがストップワードとして定義されている場合は、ワードthisを問い合せても、ヒットは戻りません。
Oracle Textの索引では、ストップワードの索引エントリは作成しませんが、ストップワードの位置は記録しているため、this boy talks to that girlといった索引付け可能なワードに加えてストップワードを含む句を問い合せることができます。
問合せ句内にストップワードが含まれている場合、このストップワードは任意のワードに一致します。たとえば、次の問合せではwasがストップワードであると想定しています。この場合、Jack is bigやJack grew bigなどの句が一致します。また、ストップワードではありませんが、grewにも一致します。
'Jack was big'
Oracle Database 12cリリース2 (12.2)以降、ストップワードとストップワードの単項演算子が問合せ結果の初期段階で無視されるため、前のリリースと異なる問合せ結果になります。たとえば、次の問合せでは、the
がストップワードで、問合せ処理中に$
演算子とストップワードが無視されるため、ドキュメントは返されません。
SQL> select count(1) from tabx where contains(text,'$the')>0;
.
COUNT(1)
----------
0
次の問合せでは、the
ストップワードと$
演算子が無視されるため、first
が含まれているドキュメントは返されます。
SQL> select count(1) from tabx where contains(text,'first and $the')>0;
.
COUNT(1)
----------
2
6.1.6 ABOUT問合せおよびテーマ
ABOUT
問合せは、ドキュメント・テーマに対する問合せです。ドキュメント・テーマは、テキスト内で詳しく展開されている概念のことです。たとえば、US politicsのABOUT
問合せでは、アメリカの大統領選挙や外交政策に関する情報を含むドキュメントが戻る可能性があります。戻るドキュメントには、US politicsと正確に一致する句が含まれている必要はありません。
索引付け時に、ドキュメント・テーマはナレッジ・ベースから導出され、このナレッジ・ベースには、一般的な知識を表すカテゴリと概念が階層式にリストされています。たとえば、ナレッジ・カタログのテーマには、jazz music、football、Nelson Mandelaなどの具体的な概念もあります。また、テーマには、happinessやhonestyなどの抽象的な概念もあります。
索引付け中に、システムでは、ドキュメント内で詳しく展開されているが、ナレッジ・ベースには存在しないドキュメント・テーマも識別し、索引付けすることができます。
ナレッジ・ベースは、業界または問合せアプリケーション固有の概念や用語を定義して補強できます。補強した場合は、追加した概念に対するABOUT
問合せの精度が向上します。
索引内にテーマ・コンポーネントを作成すると、ABOUT
問合せのパフォーマンスが最も向上します。テーマ・コンポーネントは、英語とフランス語ではデフォルトで作成されます。
関連項目:
ストップテーマの問合せ
ABOUT
演算子を使用すると、テーマを問い合せることができます。ストップテーマは、索引付けされていないテーマです。ストップテーマは、CTX_DDL
パッケージを使用して追加および削除できます。また、索引を作成した後で、ALTER INDEX
文でストップテーマを追加することもできます。