LoginSignup
2
1

More than 5 years have passed since last update.

embulk ruby-filter を書いてみる - column名のprefixやsuffixにtypeをつけてDynamicFieldに使いたい

Last updated at Posted at 2017-04-07

きっかけ

embulk で mysql にLivedoorグルメDatasetを入れてたときにふと思いました。

column名にtypeがついてたら Elasticsearch や Solr の DynamicField に使いやすんじゃないかと。

rename filter ではできなそうで、twitterにポロッと書いたら助言を頂いて、plugin書いてみようかなと思った次第です。

普段はbash書いたり、ちょこっとPythonを書くくらいですが、たしかに書けそうな気がするなー、文字列連結するだけだもんなー、と思ったのでやってみることにしました。rubyはchefでちょっとだけ書いたことがある程度です。

embulk plugin を作ってみる

設計

column type output
name string name_s とか s_name とか
id long id_l とか l_id とか

プラグインテンプレートを作る

$ embulk new ruby-filter affix
$ tree embulk-filter-affix/
embulk-filter-affix/
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── embulk-filter-affix.gemspec
└── lib
    └── embulk
        └── filter
            └── affix.rb

3 directories, 6 files
$

動作確認できるようにしておく

  • restaurants.csv: Livedoorグルメデータセットのレストラン情報
  • seed.yml: embulk guess で使うやつ
seed.yml
in:
  type: file
  path_prefix: restaurants.csv
filters:
  - type: affix
    affix: prefix
out:
  type: stdout

filters はこんなふうに使えたらいいかな、という希望で書いてみた。

$ embulk guess seed.yml

で確認して

$ embulk guess seed.yml -o config.yml

で config.ymlを出力

試しにembulk preview

試しにpreviewしてみようとすると

$ embulk preview config.yml -L embulk-filter-affix -G
(略)
Error: Required field "option1" is not set
$

embulk-filter-affix/lib/embulk/filter/affix.rb を見ると option1 が integer で required みたいなので

(略)
filters:
  - type: affix
    affix: prefix
    option1: 10
(略)

こんな感じにして再実行してみると

$ embulk preview config.yml -L embulk-filter-affix -G
(省略)
*************************** 60 ***************************
(省略)
          example (   string) : example
           column (     long) : 1
            value (   double) : 1.0

csvに無いカラムが3つ追加され、とりあえずサンプルは動くことが確認できる。

本題:column名のprefixやsuffixにtypeをつけてたい

code

embulk-filter-affix/lib/embulk/filter/affix.rb
module Embulk
  module Filter

    class Affix < FilterPlugin
      Plugin.register_filter("affix", self)

      def self.transaction(config, in_schema, &control)
        task = {
          "affix" => config.param("affix", :string, default: "suffix"),
        }

        columns = []

        in_schema.each do |record|
          if task['affix'] == "suffix" then
            name = record.name + "_" + record.type.to_s[0]
          elsif task['affix'] == "prefix" then
            name = record.type.to_s[0]  + "_" + record.name
          else
            name = record.name
          end
          column = Column.new(nil, name, record.type)
          columns.push(column)
        end

        out_columns = columns

        yield(task, out_columns)
      end

      def init
        # initialization code:
        @affix = task["affix"]
      end

      def close
      end

      def add(page)
        page.each do |record|
          page_builder.add(record)
        end
      end

      def finish
        page_builder.finish
      end
    end

  end
end

実行結果

config.yml
(略)
filters:
  - type: affix
    affix: suffix
(略)

だと

$ embulk preview config.yml -L embulk-filter-affix -G
(略)
*************************** 62 ***************************
               id_l (     long) : 65
             name_s (   string) : 備長
(略)
     access_count_l (     long) : 2,370
       created_on_t (timestamp) : 2000-09-10 11:22:02 UTC
      modified_on_t (timestamp) : 2011-04-21 12:00:19 UTC
           closed_l (     long) : 0
config.yml
(略)
filters:
  - type: affix
    affix: prefix
(略)

だと

$ embulk preview config.yml -L embulk-filter-affix -G
(略)
*************************** 62 ***************************
               l_id (     long) : 65
             s_name (   string) : 備長
(略)
       t_created_on (timestamp) : 2000-09-10 11:22:02 UTC
      t_modified_on (timestamp) : 2011-04-21 12:00:19 UTC
           l_closed (     long) : 0

できたー!

gem を作る

$ cd embulk-filter-affix
$ rbenv install jruby-9.1.5.0
$ rbenv exec gem install bundler
$ bundle install
$ rake
embulk-filter-affix 0.1.0 built to pkg/embulk-filter-affix-0.1.0.gem.
$

とりあえずのgithub

公開してみる

gemspec 修正

gemspecファイルを修正する。

$ git diff embulk-filter-affix.gemspec
diff --git a/embulk-filter-affix.gemspec b/embulk-filter-affix.gemspec
index 11d2dfe..e8c8c5e 100644
--- a/embulk-filter-affix.gemspec
+++ b/embulk-filter-affix.gemspec
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
   spec.description   = "Affix"
   spec.email         = ["imura81gt@gmail.com"]
   spec.licenses      = ["MIT"]
-  # TODO set this: spec.homepage      = "https://github.com/imura81gt/embulk-filter-affix"
+  spec.homepage      = "https://github.com/imura81gt/embulk-filter-affix"

   spec.files         = `git ls-files`.split("\n") + Dir["classpath/*.jar"]
   spec.test_files    = spec.files.grep(%r{^(test|spec)/})
$

git commit しておく。

rubygems.org にアカウントを作っておく。

$ gem push

で認証情報を入れておく。

リリース!!!!!!!!!

$ rake release
embulk-filter-affix 0.1.0 built to pkg/embulk-filter-affix-0.1.0.gem.
Tag v0.1.0 has already been created.
Pushed embulk-filter-affix 0.1.0 to rubygems.org.
$
$ embulk gem search embulk-filter-affix
2017-04-09 10:59:20.013 +0900: Embulk v0.8.17

*** REMOTE GEMS ***

embulk-filter-affix (0.1.0)
$

Customization — Embulk 0.8 documentation

http://www.embulk.org/docs/customization.html#creating-plugins

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1