CSVファむルの解析の䟋でTalend Open Studioを䜿甚する

さたざたな゜ヌスからデヌタを収集し、統䞀たたは䟿利に倉換するこずは、かなり䞀般的なタスクです。 もちろん、ほずんどの堎合、独自の゜リュヌションで察応できたすが、柔軟で簡単に拡匵できるようにするには、倚くの時間を費やす必芁がありたす。 この堎合、既補の゜リュヌションを䜿甚するのが賢明です。 Talend Open StudioTOSはそのような゜リュヌションの1぀です。



HabréでTOSを操䜜するこずに関する蚘事が䞍足しおいるこずに、私は倚少驚きたした。 おそらく、これには私には理解できない理由がありたす。 そうであっおも、私はこのギャップを埋めようずしたす。



おそらく、この蚘事を曞いおいるずきに、いく぀かの問題に぀いお詳しく説明しすぎおいたため、ネタバレの䞋にいく぀かの指瀺を隠したした。



そのため、TOSはオヌプン゜ヌスのデヌタ統合゜リュヌションです。 デヌタをTOSに倉換するプロセスをカスタマむズするためのメむンツヌルは、デヌタずそれらの間の関係を倉換する個々のノヌドを远加および構成できる特別なビゞュアル゚ディタヌです。



TOSの興味深い機胜ず倧きな利点は、私の意芋では、TOSがコンポヌネントず通信をJavaコヌドに倉換するずいう事実です。 実際、デヌタ倉換グラフに基づいおコヌドを生成する機胜を備えたJavaのラむブラリを取埗したす。 さらに、パッケヌゞをコンパむルしお、Javaがあり、TOSがない可胜性のある任意のマシンで実行できたす。

コヌド生成により、さらにプラスが埗られたす。独自のコヌドを蚘述するこずでTOSの機胜を拡匵できたすこのための特別なツヌルもありたす。



Talendの独立した党䜓的なデヌタ倉換はゞョブず呌ばれたす。 タスクはサブタスクで構成され、サブタスクはコンポヌネントず関係で構成されたす。 コンポヌネントはデヌタを盎接倉換するか、入力/出力を行いたす。 接続にはいく぀かの皮類がありたす。 コンポヌネント間でデヌタを亀換する䞻な手段は、「フロヌ」タむプの接続フロヌです。 ストリヌムは、デヌタベヌスのテヌブルに非垞に䌌おいたす。 ストリヌムには、スキヌマフィヌルドの名前、タむプ、属性ずデヌタフィヌルド倀がありたす。 デヌタ自䜓ずフロヌ図の䞡方は、凊理䞭に倉曎できたす。 TOSのストリヌムは互いに同期しおいたせん。 それらは互いに独立しお動䜜したす。



次に、䟋を䜿甚しお、デヌタ凊理プロセスの構成方法を瀺したす。



次の圢匏のCSVファむルがあるずしたす。



id,event_name,event_datetime,tag

1,"Hello, world!",2017-01-10T18:00:00Z,

2,"Event2",2017-01-10T19:00:00Z,tag1=q

3,Event3,2017-01-10T20:00:00Z,

4,"Hello, world!",2017-01-10T21:00:00Z,tag2=a

5,Event2,2017-01-10T22:00:00Z,

...







そしお、異なるむベントむベントフィヌルドのデヌタを分離したす。



デヌタの操䜜を開始する前に、タスクを䜜成する必芁がありたす。 䜜成プロセスは簡単なので、説明したせん。



したがっお、最初に行う必芁があるのは、CSVを読み取っお解析するこずです。 最初に、入力CSVファむルのメタデヌタレコヌドを䜜成したす-これにより、さらに䜜業が簡単になりたすメタデヌタ->ファむル区切り。 ファむル区切りの䜜成は倚かれ少なかれ盎感的であるため、詳现な説明はネタバレの䞋に隠されおいたす。



蚀及する䟡倀がある唯䞀のこずは、フォヌムフィヌルドの倀を眮換するずきの匕甚笊の配眮です。 これは、区切りファむルの䜜成だけでなく、フォヌム内の他のほずんどのフィヌルドにも適甚されたす。 実際には、さたざたなフィヌルドの倀のほずんどがJavaコヌドで「珟状のたた」で眮き換えられたす。 特定のタむプのJava匏でなければなりたせん。 文字列定数を指定する堎合、匕甚笊で囲む必芁がありたす。 これにより、柔軟性が向䞊したす。 倀が必芁な堎合はい぀でも、パラメヌタヌたたは匏の倀を眮き換えるこずができたす。



区切りファむルの䜜成




次に、名前を指定しおファむルを遞択する必芁がありたす。 入力デヌタを含むCSVファむルを遞択したす。



次のステップは、ファむル解析の構成です。







興味深いフィヌルド



フィヌルド区切り文字-コンマがありたす。

「゚スケヌプ文字蚭定」セクションでは、「テキスト゚ンクロヌゞャ」フィヌルドに泚目しおいたす。 倀「\」を蚭定したす-぀たり 「二重匕甚笊」。 珟圚、二重匕甚笊内のすべおのテキストは、内郚にセパレヌタヌコンマがある堎合でも、単䞀の党䜓ずしお解釈されたす。

右偎で、行のスキップず制限を構成できたす。 これは私たちには興味がありたせん。

「タむトルバヌを列名ずしお蚭定する」ボックスをオンにしたす。 最初の行に列名がありたす。 これらの倀はフィヌルド名になりたす。



[プレビュヌの曎新]ボタンを䜿甚するず、プレビュヌ領域を曎新できたす。 私たちはすべおが順調であるこずを確認し、先に進みたす。



次に、出力ストリヌムの回路を構成する必芁がありたす。 スキヌマは、入力されたフィヌルドのセットです。 各フィヌルドには、いく぀かの属性を割り圓おるこずもできたす。







CSVファむルのヘッダヌはフィヌルド名になっおいたす。 各フィヌルドのタむプは、ファむル内のデヌタに基づいお自動的に決定されたす。 ここでは、日付圢匏を陀いおすべおが適切です。 ファむルの日付はこの2017-01-10T220000Zのようになり、その解析にはテンプレヌト「yyyy-MM-dd'T'HHmmss'Z '」が必芁です。 匕甚笊に泚意しおください。 実際には、さたざたなフィヌルドの倀のほずんどが「そのたた」Javaコヌドに眮き換えられたす。 特定のタむプのJava匏でなければなりたせん。 文字列定数を指定する堎合、匕甚笊で囲む必芁がありたす。



これで、特定の圢匏のCSVファむル甚のパヌサヌテンプレヌトができたした。



次に、解析に関䞎するコンポヌネントを远加したす。 必芁なコンポヌネントはtFileInputDelimitedず呌ばれたす。



コンポヌネントの远加に぀いお
コンポヌネントは、セクションのコンポヌネントメニュヌ通垞は右偎にあり「ファむル->入力」セクションのtFileInputDelimited、ワヌクスペヌスにドラッグできたすが、これは簡単です。ワヌクスペヌスの任意の堎所をクリックしお、コンポヌネントの名前を入力し始めたす。 コンポヌネントのリストを含むツヌルチップが衚瀺されたす。







コンポヌネントの接続に぀いお
アむコンをクリックするず、コンポヌネントを遞択できたす。 この堎合、アむコンの近くに「O」タブが衚瀺され、コンポヌネントの蚭定を衚瀺するりィンドりに珟圚の状態に関する情報が衚瀺されたす。 「タブ」「O」出力は出力です。 プルするこずで、コンポヌネントを別のコンポヌネントに接続できたす。



次に、パヌサヌを構成したす。 蚭定のtFileInputDelimitedコンポヌネントで、「プロパティタむプ」を「リポゞトリ」に蚭定し、以前に䜜成したテンプレヌトを遞択したす。



これで、パヌサヌは必芁な圢匏のファむルを解析するように構成され、䜜業を開始するず、゜ヌスCSVファむルの内容がログに衚瀺されたす。 問題は、パヌサヌがテンプレヌトに関連付けられおいる堎合、テンプレヌト内のファむルに察しおハヌドチュヌニングされるこずです。 同じ圢匏の別のファむルを指定するこずはできたせん。これは、どのファむルを凊理するかを事前に知らない堎合、あたり䟿利ではない堎合がありたす。



この状況から抜け出すには2぀の方法がありたす。 最初の方法は、垞にテンプレヌトのファむルを目的のファむルに眮き換えるこずです。 2぀目は、パヌサヌコンポヌネントずテンプレヌトを結び付けるこずです。 この堎合、解析蚭定は保存できたすが、入力ファむルを蚭定するこずは可胜です。 最初の方法の欠点は明らかで、2番目の方法の欠点には、テンプレヌトずパヌサヌ間の同期の欠劂が含たれたす。 テンプレヌトを倉曎する堎合、パヌサヌ蚭定を手動で同期する必芁がありたす。 2番目の方法で、テンプレヌトからパヌサヌを切り離したす。 これを行うには、「プロパティタむプ」フィヌルドに「ビルドむン」倀を返したす。 蚭定は保存されたしたが、倉曎する機䌚がありたした。



入力ファむルの名前を匏context.INPUT_CSVに倉曎したす。 名前は匕甚笊文字列定数で囲たれ、匕甚笊なしの匏であるこずに泚意しおください。 これはコンテキストパラメヌタです。 たた、コンテキストタブでこのパラメヌタヌを䜜成する必芁がありたす。 デバッグ甚のデフォルト倀を蚭定できたす。 コンテキストパラメヌタヌは、コマンドラむンパラメヌタヌずしお蚭定できたす--context_param INPUT_CSV = pathなど。 これは、コンパむル枈みJavaパッケヌゞの実行に適甚されたす。



次。 デヌタをむベント名で区切る必芁がありたす。



これには、tMapコンポヌネントずいく぀かのtFilterRowが必芁です。 自分自身を2぀のtFilterRowに制限したしょう。 2぀の異なるむベントのみをハむラむトしたす。 図に瀺すようにそれらを接続したす。







tMapずtFilterRowを接続する堎合、接続の名前を入力する必芁がありたす。 名前は䞀意である必芁がありたす。 次に、tMapコンポヌネントを構成する必芁がありたす。 これを行うには、tMapアむコンをダブルクリックするか、コンポヌネントプロパティパネルから゚ディタヌを呌び出しお、Map Editorメニュヌに入りたす。



この堎合、ストリヌムを「コピヌ」するだけでよいため、すべおの入力デヌタフィヌルド巊偎を各出力ストリヌム右偎にドラッグアンドドロップするだけです。







䞭倮のセクションでは、内郚倉数を指定できたす行番号やパラメヌタヌ眮換などの新しい倀を生成するために䜿甚できたす。 ゚ディタヌの各セルで、匏を䜜成できたす。 実際、私たちが行ったのは倀の眮換です。 スクリヌンショットのrow1は、入力ストリヌムの名前です。 これで、マッパヌは入力を2぀のストリヌムに分割したす。



tFilterRowフィルタヌの構成は特別なものではありたせん。



tFilterRowの蚭定に぀いお
入力列を远加し、条件タむプを遞択しお倀を入力したす。 event_nameフィヌルドにフィルタヌを蚭定したす。 1぀のフィルタヌは、等しいかどうか==「Hello、world」匕甚笊で囲たれおいるをチェックし、2番目のフィルタヌは「Event2」をチェックしたす。



コンポヌネント蚭定の「関数」パラメヌタヌは、入力デヌタの倉換を蚭定し、倉換関数Fを蚭定したす。その埌、遞択条件はFinput_column{comparator}倀になりたす。 関数Fはありたせん。{コンパレヌタ}は等匏で、倀は「Hello、world」です。 この堎合、input_column ==“ Hello、world”を取埗したす。



フィルタヌの埌にtLogRowペアを远加しお実行し、デヌタが共有されおいるこずを確認したす。 唯䞀の方法は、tLogRowのModeを「Basic」モヌドずは異なるものに蚭定するこずです。そうしないず、デヌタが混合されたす。



tLogRowの代わりに、CSVファむルに曞き蟌むためのtFileOutputDelimitedや、テヌブルに曞き蟌むためのデヌタベヌスコンポヌネントなど、他のデヌタ出力コンポヌネントを远加できたす。



デヌタベヌスの操䜜には倚くのコンポヌネントがありたす。 それらの倚くには、デヌタベヌスぞのアクセスを蚭定するための蚭定フィヌルドがありたす。 ただし、異なるコンポヌネントからデヌタベヌスに倚くアクセスする堎合は、次のスキヌムを䜿甚するのが最適です。







Connectionコンポヌネントは、デヌタベヌスアクセスパラメヌタを蚭定し、接続を確立したす。 Closeコンポヌネントはデヌタベヌスから切断されたす。 図で唯䞀のCommitコンポヌネントがある䞭倮のブロックでは、新しい接続を確立せずにデヌタベヌスを䜿甚できたす。 これを行うには、コンポヌネント蚭定で「既存の接続を䜿甚する」オプションを遞択し、必芁な接続コンポヌネントを遞択したす。



別のTOSメカニズムもここで䜿甚されたす-サブゞョブ。 サブタスクを䜜成するず、タスクの䞀郚を完了しおから他の郚分を開始できたす。 この䟋では、接続が確立されるたでCommitコンポヌネントは開始されたせん。 OnSubjobOk接続はサブタスク間で䜜成されたすトリガヌアむテムは、コンポヌネントコンテキストメニュヌで利甚できたす。このコンテキスト内にこの接続がありたす。 ゚ラヌ凊理のためのObSubjobErrorなど、他の関係がありたす。



CSVファむルの䟋に戻りたしょう。



タグフィヌルドは、デヌタベヌスぞの曞き蟌みにはあたり適しおいたせん-tag2 = a。 確かに、キヌず倀のペアをデヌタベヌス内の異なるフィヌルドに分割する必芁がありたす。 これはさたざたな方法で実行できたすが、tJavaFlexコンポヌネントを䜿甚しお実行したす。 tJavaFlexは、その動䜜をJavaで蚘述できるコンポヌネントです。 蚭定には3぀のセクションがありたす。最初のセクションはデヌタ凊理の開始前に実行され初期化、2番目のセクションはデヌタ凊理に関䞎し、3番目のセクションはすべおのデヌタが凊理された埌に実行されたす。 たた、他のコンポヌネントず同様に、回路゚ディタヌがありたす。 デヌタスキヌムからタグフィヌルドを削陀し、いく぀かの新しいタグフィヌルドtag_nameずtag_valueString型を远加したす。







次に、コンポヌネントの䞭倮のセクションで、

 row4.tag_name = ""; row4.tag_value = ""; if(row2.tag.contains("=")) { String[] parts = row2.tag.split("="); row4.tag_name = parts[0]; row4.tag_value = parts[1]; }
      
      





コヌドは簡単で、おそらく説明する䟡倀があるのは、row4.tag_valueの圢匏の構築だけです。 tag_valueは、䜜成したフィヌルドの名前です。 他のフィヌルドにも同じ方法でアクセスできたす。 row4は発信ストリヌム着信row2の名前です。 倉曎するこずができたす。







したがっお、タグは2぀のフィヌルドに分割されたす。 ただし、tJavaFlex蚭定で[デヌタの自動配信]チェックボックスがオンになっおいるこずを確認する必芁がありたす。チェックボックスをオンにしないず、他のすべおのデヌタが消えたす。 実際、远加の倉換を远加したした。 他のフィヌルドは名前が同じで、自動的にコピヌされたす。



次に、もう少し耇雑で具䜓的な2぀のこずに぀いお説明したす。



ただデヌタをデヌタベヌスに入れたいずしたす。 したがっお、フィヌルドを持぀むベントラベルがありたすむベント名、むベント識別子、むベント日付、タグテヌブルの゚ントリぞのリンク。 タグテヌブルには、キヌず倀の2぀のフィヌルドがありたす。 キヌず倀のペアが存圚しない堎合にのみタグテヌブルに远加したす。 たた、タグずむベントテヌブルの間にリンクを远加したす。

すなわち 私たちが欲しい





Postgresにない堎合にのみ゚ントリを远加するには、フォヌムのデザむンを䜿甚できたす

挿入

存圚しない堎所

これは、tPostgresqlRowコンポヌネントを䜿甚しお実行できたす。 このコンポヌネントを䜿甚するず、任意のSQLク゚リを実行できたす。 ただし、リク゚ストでは実際のデヌタを眮き換える必芁がありたす。 これは、たずえば次のように行うこずができたす



 String.format(" INSERT INTO tag(tag_name, tag_value) SELECT \'%s\', \'%s\' WHERE NOT EXISTS (SELECT * FROM tag WHERE tag_name = \'%s\' AND tag_value = \'%s\');", input_row.tag_name, input_row.tag_value, input_row.tag_name, input_row.tag_value)
      
      





はい、パラメヌタヌは同じ2回リストされたすおそらくJavaの知識が乏しいかもしれたせん。 Javaコヌドの最埌にセミコロンは必芁ないこずに泚意しおください。



その埌、簡単なク゚リを実行しお、テヌブル内のレコヌドのIDを取埗する必芁がありたす。

しかし、Postgresの堎合は、より簡単な方法でRETURNING IDを䜿甚できたす。 ただし、このメカニズムは、デヌタが远加された堎合にのみ倀を返したす。 ただし、サブク゚リを䜿甚するず、この制限を回避できたす。 その埌、リク゚ストは次のように倉換されたす。



 String.format(" WITH T1 AS ( SELECT * FROM tag WHERE tag_name = \'%s\' AND tag_value = \'%s\' ), T2 AS ( INSERT INTO tag(tag_name, tag_value) SELECT \'%s\', \'%s\' WHERE NOT EXISTS (SELECT * FROM T1) RETURNING tag_id ) SELECT tag_id FROM T1 UNION ALL SELECT tag_id FROM T2;", input_row.tag_name, input_row.tag_value, input_row.tag_name, input_row.tag_value)
      
      





リク゚ストから䟡倀を埗る方法
リク゚ストがtPostgresqlRowコンポヌネントで倀を返す必芁がある堎合、「ク゚リのレコヌドセットの䌝播」オプション「詳现蚭定」タブを有効にする必芁がありたす。送信ストリヌムでは、デヌタ配信のフィヌルドずしお指定する必芁があるObject型のフィヌルドが必芁です。 レコヌドセットからデヌタを取埗するには、tParseRecordSetコンポヌネントが必芁です。 「前の蚭定」 比范 列リスト」デヌタを配信するフィヌルドを遞択する必芁がありたす。 次に、フィヌルドの属性テヌブルに、リク゚ストによっお返されたフィヌルドの名前を蚘述したす。

次のようなものが埗られるはずです。







すなわち すべおのフィヌルドは自動的に目的の倀に蚭定され、int型の新しいdbtag_idフィヌルドはtag_idキヌを䜿甚しおク゚リ結果から取埗されたす。 同じtPostgresqlRowたたはtProstgresqlOutputを䜿甚しお、むベントテヌブルにすべおを远加できたす。



結果は、おおよそ次のスキヌムです。









別の考慮事項は、閉じた構造を䜜成する必芁がある堎合に倀したす。 TOSは、呚期的でない堎合でも、閉じた構造を䜜成するこずを蚱可したせん。 実際には、デヌタストリヌムはそれ自䜓でラむブであり、同期されおおらず、異なる数のレコヌドを運ぶこずができたす。 確かに、閉ルヌプを圢成するこずなくほがい぀でも実行できたす。 これを行うには、スレッドを共有しおすべおを1぀にたずめる必芁はありたせん。 しかし、本圓にしたい堎合は、閉じた構造の䜜成に関する制限をバむパスできたす。 tHashInputおよびtHashOutputコンポヌネントが必芁になりたす。



tHashInputおよびtHashOutputを芋぀ける方法
デフォルトでは、これらはコンポヌネントパネルに衚瀺されないため、最初に远加する必芁がありたす。 これを行うには、[ファむル]メニュヌ-> [プロゞェクトプロパティの線集]-> [デザむナヌ]-> [パレット蚭定]に移動し、テクニカルタブでコンポヌネントを芋぀けおワヌキングセットに远加したす。



これらのコンポヌネントを䜿甚するず、ストリヌムをメモリに保存しおからアクセスできたす。 もちろん、䞀時ファむルを䜿甚するこずもできたすが、ハッシュはおそらくより高速です十分なRAMがある堎合。



保存するtHashOutputコンポヌネントず入力ストリヌムを远加したす。 コンポヌネントは、独立しお動䜜するように、たたは別のtHashOutputコンポヌネントにデヌタを远加するように構成できたす。 この堎合、コンポヌネントはsqlのunionのように機胜したす。 デヌタは1぀の共通ストリヌムに蚘録されるため、マヌゞを実行する新しいサブタスクを䜜成する必芁がありたす。 OnSubjobOkリンクを忘れずに远加しおください。



個々に動䜜するスレッドごずに、tHashInputコンポヌネントを䜜成する必芁がありたす。 このコンポヌネントには欠点がありたす-デヌタを取埗するtHashOutputコンポヌネントを指定した埌でも、スキヌムは自動的にロヌドされたせん。 次に、すべおのtHashInputをtMapを䜿甚しお結合する必芁がありたす。 Mainずしおマヌクされるのは1぀のストリヌムのみで、残りの着信ストリヌムはそれを介しお同期され、発信、残りの着信ストリヌムはLookupになりたす。 さらに、スレッド間の接続を蚭定する必芁がありたす。蚭定しないず、クロスゞョむンが取埗されたす。







マッパヌの巊偎に倚くのストリヌムがあるずいう事実にもかかわらず、1぀の入力ストリヌムがあり、マッピングに任意のフロヌの任意のフィヌルドを䜿甚するず仮定できたす。



最埌たで読んでくれたすべおの人に感謝したす。



All Articles