A Day In The Boy's Life -41ページ目

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

自分の職場にも外国人の人がいたりして、そういった人から日本で働く難しさというものの中に「文化の違い」っていう言葉を耳にすることがたびたびあります。

確かに言葉だけでなく生活スタイルや企業独自のルールなどもあいまって形成される目に見えない文化というものを理解できなくは無いのですが、難しくしているのはそれだけなのかなって思ったりもします。



文化の違いって結局ルールの違い


文化って特に住む国の間にあるものだけでなく、日本国内でも仕事をしているとその企業文化というのは耳にするところです。

ですので、外国にいるからとか外国人だからってわけだけでなく、その職場や属するチームにおいても面倒なルールが蔓延して文化を形成していたりもするわけですね。


「日本人は行間を読むから多少曖昧な仕様でも適当に取り繕ってくれるけど、オフショアで出してみたら仕様どおりにしか実装してこないのな」、なんて話をされたこともあるんですけど、それって別に文化の違いってわけでもなんでもなくて、同じ日本人でも空気読む力って個人で全然違いますから当然のように品質も異なるわけで、単純に第一印象が悪かったからそう思っているんでしょうと感じたりする部分もあります。

まぁ、言葉の壁って結構でかいので細かい行間を読むどころか正しく情報を伝えられていないというところがあるのは身を持って経験していたりするところではありますけど、どちらかというとそういうのが気になるのは細かすぎる性格というか、繊細に人をコントロールしすぎようとして失敗しているのではないかと思ったりもします。


ですので文化の違いといっても、日本人である私にも適用されていて、その変なルールや規律の中で仕事をしなくてはなりませんので条件は同じです。

転職したら新しい会社での企業文化を理解していかなくてはありませんし、プログラマとしてはその環境でのコーディングスタイルや開発環境を理解していかなくてはならないってな具合にです。

過去の経験に似たようなものがあればカンが働いての見込みが早くなりますが、全くの新境地であれば一度怒られたり、指摘されて恥じかいてってな具合にその領域を埋める経験をしない限りは気づきもしません。



文化の違いの受け入れ方


文化の違いが難しいというのは、そういった独自のルールというものを覚えたり、そもそも自分が全く知らない領域のところを当たり前のように振舞われ、それに従わなくてはならないところに大変さがあったりもするんですが、簡単に言ってしまえば経験の積み重ねでどうにかなる部分でもあります。


この辺で、真っ向から覚えていこうというのは当たり前のように大変なわけですが、ただその文化を形成するのはそこにいる個の人たちの集合であるので、その人たちをよく観察してみたら見えてくるものもあって理解を助けることにはつなげられます。

要はそのローカルルールを覚えるのにいちいち手順書や規定を読んだりってな事をしなくても、そこに長くいる人と話をしたり、その人自身の行動を見てたら「あそこはあーやればいいのね」ってわかるところも多くあります。


まぁ、大概は単にその人が気分屋さんだったり、お堅い人で細かく管理しないときがすまない人であったり、取りあえず権力があるんだから俺様のルールに従えだったり、民主制で決めたものが幾年も受け継がれていたりと、そんな感じで変な文化が形成されていたりもするんですが。

結局のところ文化の違いに対応するためには、そこにいる人をよく観察したり、そこでの経験を活かして現場に適応していく能力次第なのかなと思ったりします。

まぁ、私は外国で仕事をしたこともありませんし、色んな企業を渡り歩いているわけでもないので、その文化の違いという苦労を実際のところ体験してないからそんなことが言えるのかもしれませんが。


自分の経験では、子供の頃に転校を繰り返したことがあって新しい環境にどう適応しようかと悩んだ時期がありました。

一番強烈だったのは、関西から関東に移り住んだときで、普通に関西弁で喋ったら全く通じないわけです。

当時は関西弁なんてテレビでも喋っている人が少なかったですし、ましてや子供でしたのでそれをどう標準語に翻訳すればいいのか頭を悩ませた記憶があります。

そんな環境があったからか、(職場には関西人が多いんですが)今でも関東に住んでも関西弁を喋ることは無いですし、その環境環境でどう適応していくのが一番手っ取り早く波風立たないのかなんて事を昔から考えるようになってしまいました。


話を戻すとそういった文化の違いって言うのはあるのが当然ですから難しく考えずに郷に入れば郷に従えでいいんじゃなかろうかと思います。

それは何でもかんでも従順に受け入れろということではなく、そのルールを理解してみることからスタートする必要はあります。

「文化の違いだ」なんて言葉を使ってしまえばそこで思考停止してしまって互いに歩み寄ることもできないでしょうから、単に環境が違うだけ、価値観が違うだけ、考えの方向性が違うだけとシンプルに考えてみたらいいのではと思うわけです。




前回の「Apache Solrを利用して本格的な検索エンジンを導入する 」の続き。

前回のエントリでApache Solr4.2のインストールと日本語検索の環境設定を行いましたが、今回は具体的なApache Solrの操作感をまとめていきたいと思います。



Apache Solrのデモ環境を作る


何にせよやっぱり動く環境を見ていくのが一番理解しやすいわけですが、デモサイトを一から用意してとなると結構手間になることから、下記のサイトの情報をベースに書いていきます。


第5回 全文検索エンジン「Lucene/Solr」を導入する @ ITpro


この記事はApache Solr1.3系の古いバージョンでの解説記事なので、このエントリではそれを4系のバージョンに焼きなおしたようなものになっています。


まず、P.1のSolrのインストールや環境準備は前回のエントリで整っているので割愛します。

ということで、P.2以降(要会員登録)のところからですが、簡易的な住所検索のプログラムのソースが一式ダウンロードできますので落としておきます。

このデモは、このアプリを使ってApache Solr上で住所検索をするというものです。

適宜、上記のITproのサイトも参照しながら読んでみてください。


住所検索プログラム(html、js、xslファイル)は、サーバー上にアップロード後、Apache Solrの公開ディレクトリに展開します。

便宜上、ディレクトリ名はデフォルトのCustomModulesからsearchという名前に変更しています。


$ cd /path/to/solr/example/solr-webapp/webapp/
$ cp ~/CustomModules.zip ./
$ unzip CustomModules.zip
$ mv CustomModules search
$ cd search
$ mkdir js
$ cd js
$ mv ../prototype-1.6.0.3.js ./

最後にしている作業は、prototype.jsファイルの呼び出し方がjsディレクトリにあるものを読込むようになっているため、ファイルを移動させています。

次に、Apache Solrの定義ファイル(schema.xml)をSolrのconfディレクトリに展開します。


$ cd /path/to/solr/example/solr/collection1/conf/
$ mv /path/to/solr/example/solr-webapp/webapp/search/schema.xml ./

ちなみに、collection1というのはSolrの検索エンジンのコアディレクトリになっており、コアごとに設定ファイルやデータファイルが存在します。


これで準備完了ということで住所録をSolrにインポートさせたいところですが、Apache Solr4系から幾つか仕様が変わっているめこのままだとエラーが出てうまくいきません。

そのため、先ほど展開したschema.xmlファイルを編集します。


<!--
<filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt" />
-->

上記を編集しなかった場合、Solrを起動したときに下記のようなエラーが発生します。


collection1: org.apache.solr.common.SolrException:org.apache.solr.common.SolrException: Plugin init failure for [schema.xml] fieldType "textTight": Plugin init failure for [schema.xml] analyzer/filter: Error loading class 'solr.EnglishPorterFilterFactory' 

Apache Solrではデータのインポートや検索のときに幾つかフィルタを通すことができます。

フィルタを通すことでデータを加工したり(例えば大文字を小文字にしたり、日本語の場合は形態素解析エンジンを指定したり、インデックスしないキーワードを指定したりなど)しながら利用できます。

そのフィルタが存在しないためのエラーなのですが、フィルタを使わなくても利用可能なためコメントアウトしてしまいます。


次に、fieldsタグの最後(93行目あたりの</fields>の直前)に、下記の項目を追加します。


<field name="_version_" type="long" indexed="true" stored="true"/>

これも登録しておかないと下記のようなエラーが出てしまいます。


collection1: org.apache.solr.common.SolrException:org.apache.solr.common.SolrException: Unable to use updateLog: _version_field must exist in schema, using indexed="true" stored="true" and multiValued="false" (_version_ does not exist) 

私は、Solr4系からしか触っていないのですが、どうも4系から_version_というフィールドが必須となっているようです。


これで、schema.xmlファイルの編集は完了です。

schema.xmlの詳解は「Apache Solrのschema.xmlを読み解く 」にもまとめていますので参考にしてみてください。


もし、Solrを起動している場合は再起動しておきます。

前回のエントリで書いたように児童起動スクリプトを用意している場合は、


# /etc/init.d/solr restart

のようにしておきます。



Apache Solrへデータをインポートする


これでようやくSolrに住所録データを登録できるので、サーバーに展開したディレクトリに含まれるzip-code.xmlをSolrに取り込みます。


$ cd /path/to/solr/example/exampledocs
$ ./post.sh zip-code.xml
Posting file zip-code.xml to http://localhost:8983/solr/update

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader"><int name="status">0</int><int name="QTime">21506</int></lst>
</response>
<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader"><int name="status">0</int><int name="QTime">352</int></lst>
</response>

post.shは、Solrに付属しているSolrと対話するためのシェルスクリプトです。

Solrとの対話はRESTなAPIを通して行います。

post.shのシンプルなシェルスクリプトの中身を見ればわかりますが、実質


curl $URL --data-binary @$f -H 'Content-type:application/xml'

という一行だけで、このようにHTTPを通してSolrにデータの取り込みや検索など様々な実効命令が行えます。

要はHTTPクライアントとして動作する環境があればよいので、その他のプログラムからも簡易的に対話プログラムを書く事ができます。


もし、住所録データの取り込みがうまくいかない場合は、zip-code.xmlの文字コード周りかもしれません。

私の場合、サーバー環境がEUC-JPだったため少してこずったりしました。

zip-code.xmlをEUCで保存して、iconvなどからUTF-8に変換しなおして取り込んだらうまくいったりしました。


ここまでうまくいったら一旦、Solrの管理サイトから検索を実行してみましょう。

Solr管理サイトにアクセスし、左下のリストボックスから「collection1」を選択し、Queryメニューを開きます。

そこで、何も入力・変更しない状態で下のほうにある「Execute Query」ボタンをクリックして結果が表示されればうまく取り込まれています。


A Day In The Boy&#39;s Life-ApacheSolrで検索


データの取り込みと管理サイト上での検索がうまくいったらデモ環境の構築に戻りましょう。


http://localhost:8983/solr/search/search.html


へアクセスしてみます。

これで、ITproの記事で解説されているように住所検索システムへアクセスできます。


A Day In The Boy&#39;s Life-ApacheSolrデモサイト


しかし、最初のテキストボックスに例えば都道府県名を入力して検索しても何も反応がありません。

先ほど検索してみた、Solrの管理サイトのQueryメニューから「q」と書かれたテキストエリアに都道府県名を入力してみても同様にヒットしません。


<?xml version="1.0" encoding="UTF-8"?>
<response>

<lst name="responseHeader">
  <int name="status">400</int>
  <int name="QTime">1</int>
  <lst name="params">
    <str name="indent">true</str>
    <str name="q">北海道</str>
    <str name="_">1368198319211</str>
    <str name="wt">xml</str>
  </lst>
</lst>
<lst name="error">
  <str name="msg">undefined field text</str>
  <int name="code">400</int>
</lst>
</response>


この理由は、キーワードの検索対象フィールドが設定ファイル内で定義されているためです。

試しに検索キーワードに「prefecture:北海道」と入力して検索してみるとヒットするはずです。

これは、prefectureフィールドに対して検索しろって指定になります。
エラーメッセージにあるようにデフォルトでは、textという名前のフィールドに対して検索をしており、そのようなフィールドは取り込んだデータの中では存在していないためエラーを返してきます。

ということで、Solrの設定ファイル(solrconfig.xml)を編集します。


$ cd /path/to/solr/example/solr/collection1/conf/
$ vi solrconfig.xml

この中で、774行目あたりに検索実施時のデフォルトで検索するフィールド(dfという名前のフィールド)が定義されていますので、コメントアウトしてしまいます。


  <requestHandler name="/select" class="solr.SearchHandler">
    <!-- default values for query parameters can be specified, these
         will be overridden by parameters in the request
      -->
     <lst name="defaults">
       <str name="echoParams">explicit</str>
       <int name="rows">10</int>
       <!-- <str name="df">text</str> -->
     </lst>


編集が完了したらSolrの再起動が必要です。


これで再度、都道府県名だけで検索してみると結果が表示されるはずです。


A Day In The Boy&#39;s Life-ApacheSolrデモサイトでの検索結果


ということで、デモサイトが出来上がったのでSolrの検索の最初の最初に触れる環境が整いました。

具体的な使い方を書きたいところですが、エントリも長くなったのでまた次回に。





情報を検索するというのは、どんなサービスであれ重要な機能になってきますが、単純なDB検索などでは情報の精度が悪かったり、パフォーマンスが出ないといった問題が出てきます。

SQLのLIKE文ではIndexが使われなかったり、あいまい検索をすると余計な情報が引っかかったりして、その検索順位のスコア付けをしようとすると別のロジックが必要になってきたりして、かなり複雑な処理になってきます。


そんなこんなで億劫になってしまう検索システムですが、Apache Solr を利用すると手軽に高度な検索システムを導入することができます。



Apache Solrをインストールする


Apache SolrはJavaで書かれているため、利用するためにはJava(バージョン1.5以上)の環境を用意する必要があります。

今回の環境では、CentOS6.4にApache Solr4.2をインストールします。


Javaの環境が用意されていない場合は、yum経由とかでインストールしておきましょう。


# yum install java-1.6.0-openjdk.x86_64
# yum install java-1.6.0-openjdk-devel.x86_64
# yum install ant.x86_64

antは、後で説明する形態素解析用エンジンであるSenを利用する際に必要になってきますのであわせて準備しておきます。


Javaの環境が整ったら、Apache Solrのソースファイルをダウンロード します。

ファイルのダウンロードが終わったらサーバーにアップロードし、適当なディレクトリに展開します。


最もシンプルに使う方法としては、インストールはたったこれだけで完了です。

試しにApache Solrを起動してみます。

起動用のjarファイルがexampleディレクトリ内にあります。


# cd /path/to/solr/example/
# java -jar start.jar >> /var/log/solr.log 2>&1 &

これで起動完了です。

エラーがある場合は、ログに書き出されるので確認してみましょう。

ちなみに、デフォルト設定だとApache Solrは8983ポートを使います

iptablesの設定をしている場合は、そのポートを解除しておきましょう。


起動ができたら、管理サイトにアクセスしてみましょう。


http://localhost:8983/solr/#/


下記のような管理サイトが表示されたらインストール成功です。


A Day In The Boy&#39;s Life-ApacheSolr管理サイト


ちなみに、このインストール方法はSolrに内蔵されているJettyを利用しているため、既存環境にApacheが動いていても平行稼動ができます。

利用する際のポート番号を変えたい場合は、下記Jetty用のファイルを編集しましょう。


/path/to/solr/example/etc/jetty.xml

最後に、毎回start.jarファイルをたたくのも面倒なので、自動起動用スクリプトを作って/etc/init.d(と、ランレベルに応じてrc3.dとか)に配置しておきます。


#!/bin/sh
# chkconfig: 345 90 90
# description: Solr Boot
JETTY_HOME_DIR=/path/to/solr/example/
cd $JETTY_HOME_DIR
JAVA="/usr/bin/java"
LOG_FILE="/var/log/solr.log"

KEY=stopkey
CORE=solr
cd $JETTY_HOME_DIR
start() {
  $JAVA -Dsolr.solr.home=$CORE -DSTOP.PORT=8079 -DSTOP.KEY=$KEY -jar start.jar >> $LOG_FILE 2>&1 &
  echo "Solr started!"
}

stop() {
  $JAVA -DSTOP.PORT=8079 -DSTOP.KEY=$KEY -jar start.jar --stop
  echo "Solr stopped!"
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
      stop
      start
      ;;
    *)
      echo "Usage: $0 {start|stop|restart}"
      exit 1
esac


chkconfigとかはお好みでどうぞ。



形態素解析エンジンSenをインストール


ここまでの作業でSolrは利用可能になっていますが、データに日本語が入っている場合は検索できません。

英文と違って日本語は単語の区切りがわかりづらいので、形態素解析を使って文章内のキーワードを抽出する仕組みが必要になってきます。

Senは形態素解析エンジンのMeCabをJava用のライブラリとして移植したものです。


Senのソースファイルのダウンロードはブラウザ経由でできないため、SVN経由で落としてきます。


$ svn co https://svn.java.net/svn/sen~svn/tags/SEN_1_2_2_1/sen
$ cd sen
$ ant


「BUILD SUCCESSFUL」というメッセージが最後に表示されたら完了です。

Senのビルドが終わったら形態素解析の元データとなる辞書登録を行います。

今回はIPAdic legacy を使います(バージョン2.7)。

上記のサイトから辞書データのtarボールをダウンロードしてサーバーにアップしておきます。


元々、Sen自体の辞書登録スクリプト(ビルド用ファイル)がIPAdicを使うようになっているのですが、Senのバージョン1.2.2.1ではこの辞書登録用のスクリプトが古くそのままだと動かないので編集します。


$ cd /path/to/sen/dic

上記フォルダ内にある、build.xmlを編集します。

まずは、17行目あたりにあるバージョン情報を「2.6.0」から「2.7.0」に変更。


<property name="ipadic.version" value="2.7.0"/>

次に、このビルド用のファイルはサーバーから直接ファイルをダウンロードして辞書登録する仕組みになっていますが、そのパスに現在はファイルが存在しません。

そして、先ほど辞書データをダウンロードしてサーバーにアップしているのでそちらを利用してもらうように編集します。

具体的には、サーバーから直接取りにいく処理をコメントアウトしてしまいます(64行目あたり)。


  <target name="download" depends="prepare-proxy,prepare-archive,prepare-dics0,prepare-dics" unless="ipadic.archive.present">
<!--
    for proxy
    <setproxy socksproxyhost="proxyhost" proxyport="8080" />
    <get src="${ipadic.home}/${ipadic.archive}" dest="${ipadic.archive}" />
-->
  </target>
  <target name="melt" depends="download,prepare-dics" unless="dics1.present">
<!--
    <gunzip src="${ipadic.archive}"/>
    <untar src="${ipadic.dir}.tar" dest="." />
    <delete file="${ipadic.dir}.tar"/>
-->
  </target>


そして、先ほどアップしておいた辞書データをSenの辞書データ保管用のディレクトリに移動させます。


$ cd /path/to/sen/dic
$ cp -R /path/to/ipadic-2.7.0 ./
$ ant


こちらも最後に「BUILD SUCCESSFUL」というメッセージが出てきたらビルド完了です。
最後に、出来上がった辞書用のライブラリをSolrに組み込みます。


$ cd /path/to/sen/lib
$ cp sen.jar /path/to/solr/example/solr-webapp/webapp/WEB-INF/lib/

この一連の作業で、Apache Solrで形態素解析が利用できるようになります。


以下、余談ですがSenのインストール時にエラーが出た場合の対処です。

まず、Senをantでビルドする際に文字コードに関するWarningが出たりします。


compile:
    [javac] Compiling 31 source files to /path/to/sen/build/classes
    [javac] /path/to/sen/src/java/net/java/sen/SenUtils.java:158: warning: unmappable character for encoding euc_jp

が、これは基本的にメッセージなので無視してかまいません。

そして、個人的にはまったのが


[javac] /path/to/sen/src/java/net/java/sen/util/DoubleArrayTrie.java:1: class or interface expected
    [javac] cpp: error trying to exec 'cc1plus': execvp: No such file or directory
    [javac] ^
    [javac] /path/to/sen/src/java/net/java/sen/util/DoubleArrayTrie.java:1: unclosed character literal
    [javac] cpp: error trying to exec 'cc1plus': execvp: No such file or directory
    [javac]                           ^
    [javac] /path/to/sen/src/java/net/java/sen/util/DoubleArrayTrie.java:1: unclosed character literal
    [javac] cpp: error trying to exec 'cc1plus': execvp: No such file or directory

というエラーで、結論から言うとJavaやantの環境ではなく、gccやgcc-c++パッケージが入っていなかったために起きるという問題でしたので、yum経由でパッケージをインストールしたらantのビルドがうまくいきました。


そして、Solrの具体的な使い方の話を書いていきたいのですが、記事が結構長くなってしまったので、また次回にまとめていきたいと思います。