14 ファセット・ナビゲーションの使用
ファセット・ナビゲーション機能について理解します。
この章のトピックは、次のとおりです:
14.1 ファセット・ナビゲーションについて
この機能は、eコマースまたはカタログ・アプリケーションでよく使用される、ファセットとも呼ばれるグループ集計を実装します。多くのアプリケーションでは、問合せによって返されたヒットのリストを表示するだけでなく、その結果がカテゴリ化されていることが望まれます。
たとえば、eコマース・アプリケーションで、マネジメントという語句に対する問合せに一致するすべての製品をそのファセット情報とともに表示するとします。ファセットには、「製品のタイプ」(本やDVD)、「著者」および「日付」があります。各ファセットに対して、アプリケーションでは一意の値(本やDVD)とその件数が表示されます。「本」カテゴリに分類される、関心がある製品のほとんどをすばやくアセスメントできます。「製品のタイプ」で「本」を選択して、検索をさらに絞り込むことができます。
グループ集計は特定の値を持つドキュメントの数として定義されます。値が同じドキュメント内で繰り返されている場合、そのドキュメントによりその値の合計グループ集計に加えられる件数は1です。グループ件数つまりファセットは、optimized_for search
SDATA
を使用するSDATA
セクションでサポートされています。問合せのファセットの計算をリクエストするには、結果セット・インタフェースを使用します。
14.2 ファセットとしてのセクションの定義
SDATA
は構造化データを参照します。グループ件数つまりファセットは、optimized_for
属性を'search'または'sort and search'に設定して作成するSDATA
セクションでサポートされています。MULTI_COLUMN_DATASTORE
プリファレンスで、データがoptimized_for search
SDATA
として指定されたタグや列の間にあると、そのデータは自動的にファセット・データとして索引付けされます。宣言されたタイプと一致しないデータは、特定の行の索引付けエラーをそのときに処理しているのと同じフレームワークに基づいて処理されます。
例
次の文では、いくつかのタグ付けされたデータが表のVARCHAR2
列に挿入されます。後から、ここで使用されたタグに基づいてデータを収集するためのSDATA
セクションを定義できます。
-
バイナリfloatやバイナリdoubleにはタグprice:
insert into mytab values (1, 'red marble' <price>1.23</price>');
-
タイム・スタンプにはタグT:
insert into mytab values (1,'blue marbles <T>2012-12-05T05:20:00</T>');
次の文では、セクション・グループが作成され、様々なSDATA
セクション・グループが追加されます。セクションの定義には、そのセクションが属するセクション・グループ、セクションの名前、検索するタグ、およびデータ型が含まれます。
exec ctx_ddl.create_section_group('sg','BASIC_SECTION_GROUP')
exec ctx_ddl.add_SDATA_section('sg','sec01','name', 'varchar2')
exec ctx_ddl.add_SDATA_section('sg','sec02','count', 'number')
exec ctx_ddl.add_SDATA_section('sg','sec03','date', 'date')
exec ctx_ddl.add_SDATA_section('sg','sec04','timestamp', 'timestamp')
exec ctx_ddl.add_SDATA_section('sg','sec05','new price', 'binary_double')
exec ctx_ddl.add_SDATA_section('sg','sec06','old price','binary_float')
exec ctx_ddl.add_SDATA_section('sg','sec07','timestamp','timestamp with time zone')
ファセットに付けた名前が'sec01'
で、'name'
タグは、索引付けされたドキュメント内に出現する実際のタグ名です。'date'
、'timestamp'
および'timestamp with time zone'
データ型では、入力データは標準ISO形式である必要があります。
関連項目:
標準ISOフォーマットの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。
例14-1 ファセット・ナビゲーションの使用
次の文では、products
という名前の表が作成されます。
drop table products;
create table products(name varchar2(60), vendor varchar2(60), rating number, price number, mydate date);
次の文は、値をproducts
に挿入します。
insert all
into products values ('cherry red shoes', 'first vendor', 5, 129, sysdate)
into products values ('bright red shoes', 'first vendor', 4, 109, sysdate)
into products values ('more red shoes', 'second vendor', 5, 129, sysdate)
into products values ('shoes', 'third vendor', 5, 109, sysdate)
select * from dual;
次の文は、ds
という名前のMULTI_COLUMN_DATASTORE
プリファレンスを作成して、ファセットとして使用するよう他の各種列を索引(name
)に取り込んでいます。
/*A MULTI_COLUMN_DATASTORE automatically adds tags by default so that the text to be indexed looks like
'<name>cherry red shoes</name><vendor>first vendor</vendor><rating> .... '*/
exec ctx_ddl.drop_preference ('ds')
exec ctx_ddl.create_preference('ds', 'MULTI_COLUMN_DATASTORE')
exec ctx_ddl.set_attribute ('ds', 'COLUMNS', 'name, vendor, rating, price, mydate')
ノート:
Oracleでは、binary_float、binary_double、timestamp
およびtimestamp with timezone
のデータ型を持つ表の列は許可されていません。そのため、このようなデータ型をMULTI_COLUMN_DATASTORE
で使用することは困難です。それでも、これらのデータ型のタグ付きデータがドキュメントに含まれている場合はファセットを作成できます。あるいは、'timestamp'列は'date'に変換し、binary_float
、binary_double
は'number'として格納できます。
次の文では、sg
という名前のセクション・グループを作成し、各列のoptimized_for search
属性がファセットとして処理されるようにします。
/* A Section Group is created to specify the data type of each column (varchar2 is the default) and
how each column that is brought into the index should be used.*/
exec ctx_ddl.drop_section_group ('sg')
exec ctx_ddl.create_section_group ('sg', 'BASIC_SECTION_GROUP')
exec ctx_ddl.add_sdata_section ('sg', 'vendor', 'vendor', 'VARCHAR2')
exec ctx_ddl.add_sdata_section ('sg', 'rating', 'rating', 'NUMBER')
exec ctx_ddl.add_sdata_section ('sg', 'price', 'price', 'NUMBER')
exec ctx_ddl.add_sdata_section ('sg', 'mydate', 'mydate', 'DATE')
exec ctx_ddl.set_section_attribute('sg', 'vendor', 'optimized_for', 'SEARCH')
exec ctx_ddl.set_section_attribute('sg', 'rating', 'optimized_for', 'SEARCH')
exec ctx_ddl.set_section_attribute('sg', 'price', 'optimized_for', 'SEARCH')
exec ctx_ddl.set_section_attribute('sg', 'mydate', 'optimized_for', 'SEARCH')
次の文では、name
に索引が作成され、PARAMETERS
句を使用してプリファレンスを指定します。
CREATE INDEX product_index ON products (name)
INDEXTYPE IS ctxsys.context
PARAMETERS ('datastore ds section group sg');
次の文では製品名'red shoes'を問い合せ、計算のファセットを指定できます。count
属性は製品の問合せに一致する品目の合計数を示します。結果セット・インタフェースでは、一致するアイテムが最も多い上位ベンダー、最安値、および最新の着荷など、様々な要件を指定します。
set long 500000
set pagesize 0
variable displayrs clob;
declare
rs clob;
begin
ctx_query.result_set('product_index', 'red shoes', '<ctx_result_set_descriptor>
<count/>
<group sdata="vendor" topn="5" sortby="count" order="desc">
<count exact="true"/>
</group>
<group sdata="price" topn="3" sortby="value" order="asc">
<count exact="true"/>
</group>
<group sdata="mydate" topn="3" sortby="value" order="desc">
<count exact="true"/>
</group>
</ctx_result_set_descriptor>',
rs);
/* Pretty-print the result set (rs) for display purposes.
It is not required if you are going to manipulate it in XML.*/
select xmlserialize(Document XMLType(rs) as clob indent size=2) into :displayrs from dual;
dbms_lob.freetemporary(rs);
end;
/
select :displayrs from dual;
出力は次のようになります。
<ctx_result_set>
<count>3</count>
<groups sdata="VENDOR">
<group value="first vendor">
<count>2</count>
</group>
<group value="second vendor">
<count>1</count>
</group>
</groups>
<groups sdata="PRICE">
<group value="109">
<count>1</count>
</group>
<group value="129">
<count>2</count>
</group>
</groups>
<groups sdata="MYDATE">
<group value="2017-12-06 05:44:54">
<count>3</count>
</group>
</groups>
</ctx_result_set>
14.3 結果セット・インタフェースを使用したファセットの問合せ
Oracle Databaseリリース18から、指定されたファセットのリストのグループ・カウント操作が用意されています。bucketby
属性の値をsingle
に設定して使用することで、単一の値ごとにグループ・カウントを取得できます。topn
、sortby
およびorder
属性もサポートされています。
-
このリリースでは、
single
が有効な唯一の属性です。 -
'single'モードでは、ファセットのすべての一意の値のリスト、および各値のドキュメント・カウントが生成されます。
-
有効な属性値は、0より大きい正の数です。
-
この属性は、上位
n
件のファセット値とそのカウントのみを返すよう指定します。 -
グループ・カウントにより、
sortby
属性がvalue
に設定されている場合の除き、返される上位n
件の値が決定されます。その場合、値はデータ型に従ってソートされ、ソートの上位n
件の結果が返されます。ソートにおいては順序属性が考慮されます。 -
デフォルトでは、結果はグループ・カウントを基準として降順でソートされます。
-
カウントに同順位がある場合、この同順位内のファセット値の順序は保証されません。
単一件数
次の文は、表mytab
にいくつかの行を挿入します。一部の行にはファセット<B>
の値が2つあり、一部の行には単一の値があります。
begin
insert into mytab values (1, '<B>1.234</B><B>5</B>');
insert into mytab values (2, '<B>1.432</B>');
insert into mytab values (3, '<B>2.432</B><B>6</B>');
insert into mytab values (4, '<B>2.432</B>');
end;
単一件数では、一意のそれぞれの値と、その値を持つドキュメントの数を表示します。
<ctx_result_set>
<groups sdata="SEC01">
<group value="2.432"><count>2</count></group>
<group value="1.234"><count>1</count></group>
<group value="5"><count>1</count></group>
<group value="6"><count>1</count></group>
<group value="1.432"><count>1</count></group>
</groups>
</ctx_result_set>
ドキュメント1が削除されると、次のような結果になります。
<ctx_result_set>
<groups sdata="SEC01">
<group value="2.432"><count>2</count></group>
<group value="6"><count>1</count></group>
<group value="1.432"><count>1</count></group>
</groups>
</ctx_result_set>
-
sortby
は属性値"count"および"value"をサポートしています。-
count
はグループ件数(数値)でソートします。これはデフォルトです。 -
value
は、データ型に応じて、値でソートします。
-
-
order
では、ASC
(昇順)およびDESC
(降順) (こちらがデフォルト)がサポートされています。 -
選択されていない場合、デフォルトはcount
DESC
です。
この例は、bucketby
がsingle
に設定されている場合の数値ファセットのグループ化を示しています。ここで、mytab_idx
は索引の名前、text
が問合せであり、グループSDATA
がファセットを要求しています。
begin
ctx_query.result_set('mytab_idx', 'text',
'<ctx_result_set_descriptor>
<group sdata="sec01" topn = "4" sortby = "value" order="asc" bucketby="single">
<count/>
</group>
</ctx_result_set_descriptor>'
:rs);
end;
次に、sortby
属性がcount
ではなくvalue
に設定されているために、値がアルファベット順にリストされているサンプル出力を示します。order
属性がasc
に設定されているため、値は昇順(ABCからXYZ)で表示されます。topn
属性が4
に設定されているため、4つの値のみが表示されます。
<ctx_result_set>
<group SDATA="SEC01">
<group value="ABC"><count>2</count>
</group>
<group value="DEF"><count>1</count>
</group>
<group value="GHI"><count>10</count>
</group>
<group value="XYZ"><count>1</count>
</group>
</ctx_result_set>
14.4 フィルタとしてファセットを使用した問合せの絞込み
CONTAINS
問合せがサポートされるようになりました。次の例は、'name' varchar2セクションに基づいています。数字とともに使用する場合、検索する数字を引用符で囲まないでください。contains (text, 'SDATA(sec01 = "run")', 1) > 0
contains (text, 'SDATA(sec01 > "run")', 1) > 0
contains (text, 'SDATA(sec01 >= "run")', 1) > 0
contains (text, 'SDATA(sec01 < "run")', 1) > 0
contains (text, 'SDATA(sec01 <= "run")', 1) > 0
contains (text, 'SDATA(sec01 <> "run")', 1) > 0
contains (text, 'SDATA(sec01 != "run")', 1) > 0
contains (text, 'SDATA(sec01 between "run1" and "run2")', 1) > 0
contains (text, 'SDATA(sec01 not between "run1" and "run2")', 1) > 0
contains (text, 'SDATA(sec01 is null)', 1) > 0
contains (text, 'SDATA(sec01 is not null)', 1) > 0
contains (text, 'SDATA(sec01 like "%run")', 1) > 0
contains (text, 'SDATA(sec01 like "run%")', 1) > 0
contains (text, 'SDATA(sec01 like "%run%")', 1) > 0
contains (text, 'SDATA(sec01 not like "%run")', 1) > 0
contains (text, 'SDATA(sec01 not like "run%")', 1) > 0
contains (text, 'SDATA(sec01 not like "%run%")', 1) > 0
contains (text, 'SDATA(sec02 = 9)', 1) > 0
contains (text, 'SDATA(sec02 < 10)', 1) > 0
contains (text, 'SDATA(sec02 between 2 and 20)', 1) > 0
比較演算子は、各種のデータ型に対する現在のoptimized_for search
SDATA
の動作に基づいて動作します。
14.5 複数値ファセット
複数の値が同じ文書のoptimized for search SDATA
セクションにある場合、値がSDATAセクションに対応するそれぞれのタグで囲まれていれば、各値が索引付けされます。値が個別にセクション・タグで囲まれておらず、同じセクション・タグ内に一緒にある場合、単一の値として処理されます。
たとえば、ドキュメント内にある<car>First Car, Second Car</car>
は、'First Car, Second Car'という値の単一文字列として処理されます。しかし、<car>First Car</car><car>Second Car</car>
はドキュメントにおいて別個の2つの値として処理されます。