テキスト・ファイル・アダプタは、HDFSに格納されているテキスト・ファイルの読取りおよび書込みを実行する関数を提供します。この項の内容は次のとおりです。
問合せで組込み関数を使用するには、次のようにテキスト・ファイル・モジュールをインポートする必要があります。
import module "oxh:text";
テキスト・ファイル・モジュールには、次の関数が含まれています。
例については、「テキスト・ファイル・アダプタの関数の例」を参照してください。
HDFS内のテキスト・ファイルのコレクションにアクセスします。ファイルを分割して、複数のタスクで並列で処理できます。
HDFS内のテキスト・ファイルのコレクションにアクセスします。ファイルを分割して、複数のタスクで並列で処理できます。関数によって、各ファイルの各行はXMLドキュメントとして解析されて返されます。したがって、各行には1つのXMLドキュメントが完全に含まれ、XMLの改行はXML文字参照を使用してエスケープされる必要があります。
行を、問合せの出力ディレクトリ内のテキスト・ファイルに書き込みます。行は1つ以上のファイルに展開されます。
注意
作成されるファイル数は、問合せがどのように複数のタスクに分散されているかによって異なります。各ファイルの名前は「part」で始まります(例: part-m-00000)。問合せの実行時に、出力ディレクトリを指定します。「問合せの実行」を参照してください。
XMLをテキスト・ファイルの行に書き込みます。行は、問合せの出力ディレクトリ内の1つ以上のファイルに展開されます。
XMLが複数の行にスパンしないように、シリアライズされたXMLの改行文字は文字参照に置換されます。たとえば、

は改行文字(\n
)に置換されます。
注意
作成されるファイル数は、問合せがどのように複数のタスクに分散されているかによって異なります。各ファイルの名前は「part」で始まります(例: part-m-00000)。問合せの実行時に、出力ディレクトリを指定します。「問合せの実行」を参照してください。
行を、問合せの出力ディレクトリ内にあるtrace-*という名前のテキスト・ファイルに書き込みます。行は1つ以上のファイルに展開されます。
この関数を使用すると、別の出力に簡単に書き込むことができます。たとえば、トレース・ファイルを作成して問合せ内の無効な行を識別しながら、データをOracleデータベース表にロードできます。
この例では、HDFS内の次のテキスト・ファイルを使用します。ファイルには、異なるWebページへのアクセス・ログが格納されます。各行はWebページへのアクセスを表し、時間、ユーザー名、アクセスしたページが格納されます。
mydata/visits1.log 2013-10-28T06:00:00, john, index.html, 200 2013-10-28T08:30:02, kelly, index.html, 200 2013-10-28T08:32:50, kelly, about.html, 200 2013-10-30T10:00:10, mike, index.html, 401 mydata/visits2.log 2013-10-30T10:00:01, john, index.html, 200 2013-10-30T10:05:20, john, about.html, 200 2013-11-01T08:00:08, laura, index.html, 200 2013-11-04T06:12:51, kelly, index.html, 200 2013-11-04T06:12:40, kelly, contact.html, 200
次の問合せは、john
がアクセスしたページをフィルタ処理し、アクセスした日付とページのみを新規テキスト・ファイルに書き込みます。
import module "oxh:text"; for $line in text:collection("mydata/visits*.log") let $split := fn:tokenize($line, "\s*,\s*") where $split[2] eq "john" return text:put($split[1] || " " || $split[3])
この問合せは、次の行を含むテキスト・ファイルを作成します。
2013-10-28T06:00:00 index.html 2013-10-30T10:00:01 index.html 2013-10-30T10:05:20 about.html
次の問合せは、ページに対する1日当たりのアクセス数を計算します。
import module "oxh:text"; for $line in text:collection("mydata/visits*.log") let $split := fn:tokenize($line, "\s*,\s*") let $time := xs:dateTime($split[1]) let $day := xs:date($time) group by $day return text:put($day || " => " || count($line))
この問合せは、次の行を含むテキスト・ファイルを作成します。
2013-10-28 => 3 2013-10-30 => 3 2013-11-01 => 1 2013-11-04 => 2
次の注釈を使用して、HDFS内のテキスト・ファイルのコレクションを読み取る関数を定義できます。これらの注釈によって、組込み関数では使用できない追加機能を使用できます。
シグネチャ
テキスト・ファイルを読み取るカスタム関数には、次のいずれかのシグネチャが必要です。
declare %text:collection("text") [additional annotations] function local:myFunctionName($uris as xs:string*) as xs:string* external; declare %text:collection("xml") [additional annotations] function local:myFunctionName($uris as xs:string*) as document-node()* external;
注釈
text
collection関数を宣言します。必須。
オプションのmethodパラメータは次のいずれかの値です。
text
: テキスト・ファイルの各行はxs:string
として返されます。デフォルト。
xml
: テキスト・ファイルの各行はXMLとして解析され、document-node
として返されます。各XMLドキュメントは、1行に完全に含まれる必要があります。ドキュメント内の改行文字は、数値の文字参照によって表される必要があります。
最大分割サイズを整数または文字列値で指定します。分割サイズによって、入力ファイルがタスクに分割される方法を制御します。Hadoopは、分割サイズをmax($split-min, min($split-max, $block-size))
で計算します。オプション。
文字列値の場合、バイト(デフォルトの単位)のかわりに、K
、k
、M
、m
、G
またはg
を値に追加してキロバイト、メガバイトまたはギガバイトを表すことができます。これらの修飾子は大文字と小文字を区別しません。次の例は同等です。
%xmlf:split-max(1024) %xmlf:split-max("1024") %xmlf:split-max("1K")
最小分割サイズを整数または文字列値で指定します。分割サイズによって、入力ファイルがタスクに分割される方法を制御します。Hadoopは、分割サイズをmax($split-min, min($split-max, $block-size))
で計算します。オプション。
文字列値の場合、バイト(デフォルトの単位)のかわりに、K
、k
、M
、m
、G
またはg
を値に追加してキロバイト、メガバイトまたはギガバイトを表すことができます。これらの修飾子は大文字と小文字を区別しません。次の例は同等です。
%xmlf:split-min(1024) %seq:split-min("1024") %xmlf:split-min("1K")
次の注釈を使用して、HDFS内のテキスト・ファイルを書き込む関数を定義できます。
シグネチャ
テキスト・ファイルを書き込むカスタム関数には、次のいずれかのシグネチャが必要です。
declare %text:put("text") [additional annotations] function text:myFunctionName($value as xs:string) external; declare %text:put("xml") [additional annotations] function text:myFunctionName($value as node()) external;
注釈
text
put関数を宣言します。必須。
オプションのmethodパラメータは次のいずれかの値です。
text
: データをテキスト・ファイルに書き込みます。デフォルト。
xml
: データをXMLファイルに書き込みます。XMLはシリアライズされ、改行文字は文字参照に置換されます。これによって、そのXMLドキュメントは改行のない1行のテキスト行になります。
出力で使用する圧縮形式を指定します。デフォルトは圧縮なしです。オプション。
codecパラメータは圧縮コーデックを識別します。値が一致して、最初に登録された圧縮コーデックが使用されます。値は、次のいずれかと等しい場合にコーデックに一致します。
コーデックの完全修飾されたクラス名
コーデックの修飾されていないクラス名
Codec (大文字と小文字を区別しない)の前にある、修飾されていないクラス名の接頭辞
次のすべての例では、デフォルトのコーデックおよびブロック圧縮を使用します。
%text:compress("org.apache.hadoop.io.compress.DefaultCodec", "block") %text:compress("DefaultCodec", "block") %text:compress("default", "block")
出力ファイル名の接頭辞を指定します。デフォルトの接頭辞はpart
です。
%text:put
で指定される出力方法(テキストまたはXML)に対する標準XQueryシリアライズ・パラメータ。「シリアライズ注釈」を参照してください。
現在、サポートされている文字エンコードはUTF-8のみです。
この例は、fn:tokenize
関数を使用して、テキスト・ファイルの行を解析します。この方法は、単純なデリミタ付き形式に適しています。
次の問合せは、カスタムのput
関数およびcollection
関数を宣言します。これは、ログ内のページごとに、ヒット数および一意のユーザー数を計算します。
import module "oxh:text"; declare %text:collection("text") %text:split-max("32m") function local:col($uris as xs:string*) as xs:string* external; declare %text:put("xml") %text:compress("gzip") %text:file("pages") function local:out($arg as node()) external; for $line in local:col("mydata/visits*.log") let $split := fn:tokenize($line, "\s*,\s*") let $user := $split[2] let $page := $split[3] group by $page return local:out( <page> <name>{$page}</name> <hits>{count($line)}</hits> <users>{fn:count(fn:distinct-values($user))}</users> </page> )
前の問合せの出力ディレクトリ名はmyoutputです。次の行がmyoutput/pages-r-*.gzに書き込まれます。
<page><name>about.html</name><hits>2</hits><users>2</users></page> <page><name>contact.html</name><hits>1</hits><users>1</users></page> <page><name>index.html</name><hits>6</hits><users>4</users></page>
ファイルはgzip
コーデックを使用して圧縮されます。次の問合せは、出力ファイルを読み取り、ページ名と合計ヒット数をプレーン・テキストとして書き込みます。collection関数によって、圧縮ファイルが自動的にデコードされます。
import module "oxh:text"; for $page in text:collection-xml("myoutput/page*.gz")/page return text:put($page/name || "," || $page/hits)
この問合せは、次の行を含むテキスト・ファイルを作成します。
about.html,2 contact.html,1 index.html,6
fn:tokenize
関数は、様々なデータ型やデリミタを含む複雑な形式には適していません。この例は、fn:analyze-string
関数を使用して、Apache共通ログ形式のログ・ファイルを処理します。
HDFS内のmydata/access.logという名前のテキスト・ファイルには、次の行が含まれています。
192.0.2.0 - - [30/Sep/2013:16:39:38 +0000] "GET /inddex.html HTTP/1.1" 404 284 192.0.2.0 - - [30/Sep/2013:16:40:54 +0000] "GET /index.html HTTP/1.1" 200 12390 192.0.2.4 - - [01/Oct/2013:12:10:54 +0000] "GET /index.html HTTP/1.1" 200 12390 192.0.2.4 - - [01/Oct/2013:12:12:12 +0000] "GET /about.html HTTP/1.1" 200 4567 192.0.2.1 - - [02/Oct/2013:08:39:38 +0000] "GET /indexx.html HTTP/1.1" 404 284 192.0.2.1 - - [02/Oct/2013:08:40:54 +0000] "GET /index.html HTTP/1.1" 200 12390 192.0.2.1 - - [02/Oct/2013:08:42:38 +0000] "GET /aobut.html HTTP/1.1" 404 283
次の問合せは、サーバーがステータス・コード404 (見つかりません)エラーを返した場合に、2013年9月以降に行われた要求を計算します。正規表現およびfn:analyze-string
を使用して、ログ・エントリのコンポーネントを照合します。例1に示すように、時間書式はxs:dateTime
に直接キャストできません。かわりに、ora-fn:dateTime-from-string-with-format
関数によって、文字列をxs:dateTime
のインスタンスに変換します。
import module "oxh:text"; declare variable $REGEX := '(\S+) (\S+) (\S+) \[([^\]]+)\] "([^"]+)" (\S+) (\S+)'; for $line in text:collection("mydata/access.log") let $match := fn:analyze-string($line, $REGEX)/fn:match let $time := ora-fn:dateTime-from-string-with-format( "dd/MMM/yyyy:HH:mm:ss Z", $match/fn:group[4] ) let $status := $match/fn:group[6] where $status eq "404" and $time ge xs:dateTime("2013-10-01T00:00:00") let $host := $match/fn:group[1] let $request := $match/fn:group[5] return text:put($host || "," || $request)
この問合せは、次の行を含むテキスト・ファイルを作成します。
192.0.2.1,GET /indexx.html HTTP/1.1 192.0.2.1,GET /aobut.html HTTP/1.1
関連項目:
|