カテゴリー: テクノロジー

Apache Solr を Eclipse でリモートでデバッグ

はじめに

先日、久しぶりに全文検索エンジン Apache Solr に触れる機会がありました。
現時点の最新版は 7.5 です(この記事を書いている間に 7.6 がリリースされました)。以前に扱ったことのある 5.5 からはかなり色々なところが変わっているようです。

Solr は OSS なので変更点の詳細を追いかけたければソースを読めばいいのですが、Solr くらいの規模のソフトウェアとなるとソースを読むだけでは取っ掛かりが掴みにくいことも有ります。たとえば、この factory オブジェクトが生成したのはどの具象クラスなんだ、とか、この if 文の分岐はどっちが使われるんだ、とか。そういう場合にはデバッガが役に立ちます。
今回は以下のような構成でデバッガを動かすための手順をまとめました。

  • Solr 7.5 バイナリパッケージ(稼働用)
  • Solr 7.5 ソースパッケージ(デバッガ参照用)
  • Eclipse IDE for Java Developers Version 2018-09

Solr のインストール

    1. 公式サイトからsolr-7.5.0.tgzをダウンロード。
    2. 展開
$ tar zxf solr-7.5.0.tgz
$ cd solr-7.5.0
  1. サンプル設定で起動
    $ bin/solr -e cloud
    (略)
    To begin, how many Solr nodes would you like to run in your local cluster? (specify 1-4 nodes) [2]: 1
    (略)
    Please enter the port for node1 [8983]:
    (略)
    Please provide a name for your new collection: [gettingstarted] 
    test
    (略)
    How many shards would you like to split test into? [2]
    1
    (略)
    How many replicas per shard would you like to create? [2] 
    1
    (略)
    Please choose a configuration for the test collection, available options are:
    _default or sample_techproducts_configs [_default] 
    (略)
    
  2. Solr を一旦停止しておく
    $ bin/solr stop -all
    

Solr のソースを Eclipse にインポート

  1. 公式サイトからsolr-7.5.0-src.tgzをダウンロード。
  2. 展開
    $ mkdir solr-src
    $ cd solr-src
    $ tar zxf solr-7.5.0-src.tgz
    $ mv solr-7.5.0 solr-7.5.0-src
    $ cd solr-7.5.0-src
    
  3. Eclipse のプロジェクトとして読み込めるようにビルド
    $ ant eclipse
    
  4. インポート
    1. 「ファイル」→「インポート」→「既存プロジェクトをワークスペースへ」→「次へ」
    2. 「ルート・ディレクトリの選択」で solr-src/solr-7.5.0-src を指定→「完了」

デバッグ開始

    1. Solr スタート

リモートプロセスのデバッグなので java コマンドのオプションを指定して JDWP を利用します。

$ bin/solr start -c -p 8983 -s example/cloud/node1/solr -a "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=6900"

suspend=y を指定するとデバッガが接続するまで実行を中断してくれます。ただし180以内に起動が完了しないと Solr が起動失敗と判断して自らプロセス終了してしまうので、それまでに以下の手順でデバッガを接続しなければなりません。

  1. デバッガ起動
    1. 「実行」→「デバッグの構成」
    2. プロジェクト solr-7.5.0 指定→ポート 6900 指定→「デバッグ」

動作確認

今回は Solr 6 で追加された ExtractingRequestHandler を試してみます。
このハンドラは PDF などのバイナリファイルからテキストを抽出してインデックスを作成するためのものです。solrconfig.xml では以下のように定義されています。


  <requestHandler name="/update/extract"
                  startup="lazy"
                  class="solr.extraction.ExtractingRequestHandler" >
    <lst name="defaults">
      <str name="lowernames">true</str>
      <str name="fmap.meta">ignored_</str>
      <str name="fmap.content">_text_</str>
    </lst>
  </requestHandler>

RequestHandler のメインの処理は handleRequestBody ですが、これは ExtractingRequestHandler の親クラスである ContentStreamHandlerBase クラスで定義されているので、そちらにブレイクポイントを設定しておきます。

そして PDF ファイルを post コマンドで送信します。

$ bin/post -c test -params "extractOnly=false&wt=json&indent=true" -out yes example/exampledocs/solr-word.pdf

指定しておいた場所でブレイクされます。

あとは普通にデバッガを使っていくだけです。

たとえば ExtractingDocumentLoader のこの行で変数の内容を確認すると、
実行時パラメータとして extractOnly=false だけを指定した状態では parser として AutoDetectParser、parsingHandler として SolrContentHandler が使われることが分かりました。
metadata としてどんな情報が抽出されるのかも良く分かります。

最後に

Solrのリモートデバッグは簡単です。Solr 内部の理解を深めるのに役立てたいと思います。

PDF をページ単位でインデックスする Solr の RequestHandlerを作成する

はじめに

Solr 6以降では PDF やワードなどのバイナリファイルをインデックスする機能(ExtractingRequstHandler)がサポートされています。
ファイル内に含まれるテキストをまとめて1つの文書として、メタデータ(作成日時、作成者等)と共にインデックスを作成してくれるのでこれはとても便利な機能ではありますが、用途によってはキーワードが何ページ目にヒットするのかを知りたいこともあります。そこで、自前の RequestHandler 作成の練習として PDF をページ単位でインデックスする ReqestHandler を作成してみました。

Apache Tika

Solr では PDF 等の各種フォーマットを扱うために Apache Tika を利用しています。
Tika では PDF 等を XHTML に変換した上で SAX パーサーにコンテンツハンドラを渡して XHML の要素毎の処理を実行させられます。それと同時にファイルに含まれるメタデータが Metadata クラスのオブジェクトに格納されます。
従って、Tika の呼び出し側は

  • ファイルに含まれる構造化コンテンツが XHTML に変換されたもの
  • ファイルのメタデータ

を扱うことができます。

Tika によって PDF から変換された XHTML がどんなフォーマットになっているかは、extractOnly=true オプションを指定することで見ることができます。

bin/post -c test -params "extractOnly=true&wt=json&indent=true" -out yes /tmp/test.pdf

XHTML の body 部分だけを抜粋すると以下のようになっています。

<body>
<div class="page">
<p/>
<p>テストドキュメント1ページ目です。</p>
<p/>
</div>
<div class="page">
<p/>
<p>2ページ目の文章です。</p>
<p/>
</div>
<div class="page">
<p/>
<p>これは3ページ目です。</p>
<p/>
</div>
</body>
</html>

ページ毎に

<div class="page">

に囲まれた構造になっていることが分かります。

ExtractingRequestHandler には capture という実行時パラメータがあり、これを指定することで特定の XHTML 要素(この場合div)を個別にインデックスすることができるのですが

  • 文書IDはファイル全体で共通
  • 同じ名前の要素が複数存在する場合は multivalued のフィールドに入れられる

という仕様のためページ番号との紐付けができそうもなかったのが、今回自前で実装してみようと思ったきっかけでした。

SolrがPDFを扱う仕組み

ExtractingRequestHander では以下のクラス構成で PDF 等のインデックス処理を実行しています。

  • ExtractingRequestHander
    リクエストのエントリポイント(/solr/update/extract)。

    • 設定の読み込み
    • Tika のパーサーが生成する SAX イベントを処理するコンテンツハンドラ(SolrContentHandler)用のファクトリ(SolrContentHandlerFactory)を生成
    • ExtractingDocumentLoader を生成して load メソッド(ファイル読み込みとインデックス処理のメイン)を実行
  • ExtractingDocumentLoader
    実際にファイルを読み込んでインデックス処理を実行。

    • メタデータ読み込み
    • コンテンツの種類に対応したパーサーを生成
    • ExtractingRequestHander から与えられたファクトリ(SolrContentHandlerFactory)を使ってコンテンツハンドラ(SolrContentHandler)オブジェクトを生成
    • パーサーにコンテンツハンドラ(SolrContentHandler)を与えてパース処理を実行
    • 生成されたメタデータオブジェクトとコンテンツ文字列をインデックスに投入
  • SolrContentHandler
    Tika のパーサーが生成する SAX イベントを処理する。
    基本的に XHTML に含まれるコンテンツ部分の文字列を結合して1つの大きな文字列を作っている。
  • SolrContentHandlerFactory
    SolrContentHandler のファクトリメソッドを提供する。

ページ単位のインデックス処理を実装

上記の4クラスをそれぞれ継承したクラスを実装しました。(コードはこの記事の最後に)
実装の内容は以下の通りです。

  • 設定の読み込みは親クラスに任せる
  • 具象クラスの生成処理は上書き
  • SolrContentHandler のサブクラスで
    <div class="page">
    

    を認識してページ番号とページ毎のコンテンツとが対応付けされたテーブルを作成

  • ExtractingDocumentLoader のサブクラスでページ毎に文書IDを振ってインデックス投入

利用方法

  1. 4クラスをコンパイルして Jar ファイルを生成
  2. contrib/extraction/lib に Jar ファイルをコピー
  3. solrconfig.xml の
    <requestHandler name="/update/extract"
                      startup="lazy"
                      class="solr.extraction.ExtractingRequestHandler" >
    

    の箇所を jp.co.splout.solr.plugin.MyExtractingRequestHandler に変更

  4. Solr 再起動

実行例

投入

$ bin/post -c test -params "extractOnly=false&wt=json&indent=true&literal.id=testpdf1" -out yes test.pdf

検索結果

最後に

PDF をページ単位でインデックスする Solr のプラグインを作成しました。
PoC ということで最小限の実装しかしていませんが、ちゃんとするなら

  • せっかくなのでメタデータも有効に使いたい
  • ExtractingRequestHandler の実行時パラメータで共用できるものは共用したい
  • もっというなら ExtractingRequestHandler の1機能として統合?

ということも考えたいと思います。

コード

デザインの進捗とバージョン管理のススメ

 

こんにちは。デザイン担当のLQヒロシです。

 

WEB開発ではGitというアプリケーションを用いてプログラムファイルなどの更新状況管理をしているのですが、ファイルの更新状況を上書き時に業務ログも残しています。
この業務ログは、ひとつのプロジェクトを複数人で作業することの多いエンジニアさんにとって、他のメンバーがどのような進行状況なのか、どういったところで詰まっているのかを知る目安になっています。
プロジェクトの管理担当者も作業者を評価する指標として活用しているケースもあるかと思います。

 

もちろんデザイナーもコーディング作業であればGitを使ってファイルの進行状況を管理したり業務ログを残しますが、デザイン、特にビジュアル作成フェーズの業務ログを残すのってなかなか大変で、デザイナーの管理が難しいと言われる要因の一つかもしれません。

 

弊社ではデザインデータのバージョン管理アプリを利用して業務ログを残すようにしています。今回はその取り組みについて少しご紹介したいと思います。
Gitの仕組みを利用したものになるのでバージョン管理もできるのでおすすめです。

 

デザインデータの管理アプリについて

 

よく利用されているアプリケーションは以下の2種類になるようです。

 

Kactus(カクタス)

 

Githubベースのアプリで弊社ではこちらを利用しています。
基本的にはSource treeみたいな感じで使えます。詳しくは後ほどご紹介します。

【概要】

  • 標準のバージョン管理方法はGit。
  • 対応データ形式はSketchファイルを推奨。aiファイルやpsdファイルも利用できます。Sketchファイルの場合は、png画像を自動で書き出し差分が確認できます。

 

 

Abstract(アブストラクト)

 

デザインデータのバージョン管理アプリではこちらの方が新しく評価も高いです。

【概要】

  • Gitを介さずにできるのでスムーズな導入が可能(Git連携可能)。
  • UIが特に使いやすく、Sketchとの親和性が高い。
  • Kactusよりストレスフリーで使い勝手は良いのですが、Sketchファイルにしか対応していないのが残念。

Abstractの最大の利点はデータを保存するだけででてくるコミット入力ウィジットです。Sketch限定ですがすべての作業がSketch上で完結します。これが非常に便利!!Sketch主体で業務を行っているならこちらの方が良いと思います。

 

 

弊社ではUIデザイン以外にもロゴやイラスト作成などSketch以外で作成する業務もありますのでKactusを選びました。

 

そもそもなぜデザイン業務はログが残りにくいのか?

デザイン業務、ビジュアル作成のフェーズではIllustratorなどのソフトを使ってレイアウトを組み立てていきます。

 

手書きラフなどを先に作成する場合もありますが、基本的には画面上でオブジェクトを動かしながら組み立てていくことが多いです。
色の設定から少しづつ整っていくこともありますし、漫然とした状態からアイデアがカチッとはまって次の瞬間には出来上がることもあります。
このようなところが業務ログを残すことが難しいと感じるのではないでしょうか。

 

完璧なログを残すのではなく、保存のタイミングなどで簡単な状況説明をする、もっと砕いて言えばボヤキぐらいでもいいのでアプリを活用してちょっとしたメモを残す。「誰がどんな感じで業務にタッチしているのかがわかる」ことが重要なのではと思います。
Sketchであればpng画像として自動的に残すこともできるので尚良しですね!

 

それではKactusの利用方法について

 

KactusもAbstructも使い方は検索すれば割と見つかると思います。いくつかピックアップしましたので参照ください。

Kactus – 変更点が見て分かるデザイナーのためのバージョン管理ツール
デザインデータのバージョン管理ができるAbstractを試してみた

 

書かれている内容は概ね、新規にディレクトリを作成して対象リポジトリにするという感じですので、本記事ではKactusで実際のプロジェクトとの紐付方について少しご紹介できればと思います。

 

弊社の場合はプロジェクト毎にgithubリポジトリに紐付いているため(Web開発であれば大抵そうじゃないのかなと思います)、gitクローンするところから始めます。

 

左上メニューの File > Clone Repository を選択

こちらのダイアログが表示されるので  URLタブ内、A欄に Clone 対象リポジトリーURLを B欄にClone先のディレクトリパスを入力して Cloneボタンで完了です。
※クローンするとコーディングファイルなども落ちてくるので管理には注意してください。

 

  1. 管理ディレクトリ内でデザインファイルを作成、または更新すると、ファイル変更情報が A に表示されます。
  2. A をクリックすると ※Sketch 利用時のみ B に画像が表示されます。
  3. まずはCの Fetch origin からリモートの最新バージョンを取得します。
  4. Dの Summary欄にコミットメッセージを入力。弊社の場合はRedmineと連動しているので最低限チケット番号を入力。
  5. 細かいメモはEのDescriptionに残せば良いと思います。
  6.  Commit to master をクリックすればコミット完了。

 

最後に右上の Push origin からリモートを更新して完了です。
余談ですがhtmlなどのファイルの管理もこちらからできたりします。
※プライベートリポジトリを利用するには有料の登録が必要です。

 

 

他にもHistoryからコミットログのテキストやSketchであれば差分画像を確認できます。
Redmineと連携していればそちらでもリポジトリの履歴確認が可能になります。
ブランチの作成もできますので複数人で管理することもできます。

 

 

以上、最後が駆け足になってしまいましたが、今後もKactusのナレッジなどより良い使い方をご紹介していければとおもいます。

 

 

Slackからイベントを受信

社内でのチャットツールはSlackを利用しています。
でもメッセージを見ていなかったり気づかなかったりすることがあるので、社内では確認したという反応が欲しい時は@つきでメッセージを送り、Slackのリアクション機能を使うことで確認したかどうかを判断する運用を行なっています。

 

さてここで問題です。
連休やメッセージのやり取りが流れすぎた時@つきのメッセージを追えるのか?というところです。
どうしてもメッセージが流れすぎるとリアクション漏れが発生してしまいます。
そして誰が確認していないかを確認するのも手間です。他に方法を探しましたがSlackのShow Activityの機能では求めていることが満たせません。

 

自分の職種はなんでしょうか?プログラマーです。なければ作ればいいじゃない?
幸いSlackには色々なAPIが用意されています。
そして色々触って試行錯誤した末たどり着いたのは、こちらからリクエストを投げる形式ではなくSlackからイベントを全部受け取るという方法。

概略のみになりますが、

1. メッセージを受け取って@つきのもののみ保存
2. メッセージに対してリアクションがあればリアクション情報を保存
3. メッセージに対して対象の全員がリアクション完了するとメッセージを消す

 

上記の流れでまだ自分がリアクションしていない自分宛のメッセージ一覧を残すことができるようになりました!合わせて自分が発言したメッセージに対してリアクションしていない一覧もリアクションしていない人に対して再度通知することも!

今回は使っていませんが他にも色々とできるイベントがあるようです。
Slackのアプリ作成からEvent Subscriptionsで設定できます。


 
Slackはチャット以外にも何かしらの通知や連携など色々できて便利です。
そして足りなければ自分で色々機能を追加することも用意されている。
まだ利用していなければどうぞ業務に活用することをオススメします!

Swift4でARKitを触ってみた

TikTokでホコリよけダンスを披露するため日々脳内トレーニングしてるけどダンス経験がないことを理由にビビってTikTokできていません。
マエダです。
 

 
みんな大好きiPhoneアプリ開発で必要となるプログラミング言語Swiftも気づけばバージョン4になり月日が経っていることをしみじみ実感しております。
 
前にコーポレートブログに自分が書いた記事のときはSwift2だったなんて。。。

Swift2でUISearchBarの背景透過


 
さて、そんな進化したSwiftの中でもARKitを触ってみました。

以下参考サイトです。(ありがとうございます!
https://github.com/shu223/ARKit-Sampler
https://github.com/kboy-silvergym/ARKit-Emperor
 
感想としてはAR機能をシンプルに追加できる強力な機能でした。(普通の感想すぎる・・・)
 
この強力な機能をどう活かすかで話題となっておりました3Dスキャナ。
https://www.3dscannerapp.com/
ARを身近にしたポケモンGOはデジタルと自然を調和させる楽しみ方が話題に。
http://nlab.itmedia.co.jp/nl/articles/1810/23/news113.html
 
今後もARの活用事例をチェックしながらいろいろと妄想したいと思います!
 
#TikTokerと繋がりたい