先日のSolr勉強会でドリルダウンの実装に関するセッションがあって、
その中でSolr4.0のPivot Facetingが最強じゃね?って話で、
スゲー良さげだったので自分も試してみる事にしました。
ってか、FacetPivotって何なのっていうと、、Solr4.0のWikiに以下のように書いてあります。
* Pivot Faceting – Multi-level or hierarchical faceting where the top constraints for one field are found for each top constraint of a different field.
ってことで、使うデータはこれまたSolr勉強会の際にクックパッドの@PENGUINANA_が
ElasticSeachのセッションでコレいいよーってオススメしてたlivedoorグルメさんのものを使います。
livedoor Techブログ : livedoor グルメの DataSet を公開
schema.xmlのフィールドの定義は↓こんな感じ(テキトーですいやせん、、、w)
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> <field name="name" type="text_ja" indexed="true" stored="true" omitNorms="true"/> <field name="property" type="text_ja" indexed="true" stored="true" omitNorms="true"/> <field name="alphabet" type="text_general" indexed="true" stored="true" omitNorms="true"/> <field name="name_kana" type="text_cjk" indexed="true" stored="true" omitNorms="true"/> <field name="pref_id" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="area_id" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="station_id1" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="station_time1" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="station_distance1 " type="string" indexed="true" stored="true" omitNorms="true"/> <field name="station_id2" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="station_time2" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="station_distance2 " type="string" indexed="true" stored="true" omitNorms="true"/> <field name="station_id3" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="station_time3" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="station_distance3 " type="string" indexed="true" stored="true" omitNorms="true"/> <field name="category_id1" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="category_id2" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="category_id3" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="category_id4" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="category_id5" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="zip" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="address" type="text_ja" indexed="true" stored="true" omitNorms="true"/> <field name="north_latitude" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="east_longitude" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="description" type="text_ja" indexed="true" stored="true" omitNorms="true"/> <field name="purpose" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="open_morning" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="open_lunch" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="open_late" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="photo_count" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="special_count" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="menu_count" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="fan_count" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="access_count" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="created_on" type="date" indexed="true" stored="true" omitNorms="true"/> <field name="modified_on" type="date" indexed="true" stored="true" omitNorms="true"/> <field name="closed" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="text" type="text_ja" indexed="true" stored="false" multiValued="true"/>
日本語検索するところはデフォルトのtextにcopyFieldで↓こんな感じで。
<copyField source="name" dest="text"/> <copyField source="property" dest="text"/> <copyField source="address" dest="text"/> <copyField source="description" dest="text"/>
Solrのexampledocsの中にXMLファイルをアップロード出来るサンプルがあるので、
CSVファイルをアップデートするようにシェル(post.sh)をコピって↓だけ書き換えたシェル作りやす。
curl $URL --data-binary @$f -H 'Content-type:application/csv'
前はCSVファイルを突っ込むときのURLはsolr/update/csvだったのですが、
・Solr4.0からCSVがデフォルトの UpdateHandler に取り込まれた。
・つまり solr/update でCSVも扱えるようになった。
・CSV入れる時は Content-type を application/csv か text/csv で。
という事がSolrのWiki↓に書いてありました。
http://wiki.apache.org/solr/UpdateCSV
んでシェル叩いたら、date型がinvalidとか言われてムカついたのでstringにしてやりましたw
<field name="created_on" type="string" indexed="true" stored="true" omitNorms="true"/> <field name="modified_on" type="string" indexed="true" stored="true" omitNorms="true"/>
ってことで、ようやくデータが入りました。
root@hoge:/usr/local/apache-solr-4.0.0/ldgourmet/exampledocs# /bin/sh post_csv.sh restaurants.csv Posting file restaurants.csv 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">75033</int></lst> </response> <?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"><int name="status">0</int><int name="QTime">562</int></lst> </response>
ってことで、、、
いよいよ facet.pivot してやるぜ~!と。
クエリは↓こんな感じ。自分の地元の海老名で居酒屋~
海老名&fq=category_id1:505&wt=xml&facet=true&facet.pivot=category_id1,category_id2,category_id3http://localhost:8983/solr/collection1/select?q=
結果は↓こんな感じ。検索に19ミリ秒かかって13レコード見つかりましたよ、と。
で、気になるファセットのところは↓こんな感じ。
ちなみにカテゴリはIDになってて、マスタは別CSVファイルで
↓のようになってます。
id,name,name_kana,parent1,parent2,similar 100,"和食","わしょく",0,0, 101,"懐石・精進・料亭・割烹","かいせき・しょうじん・りょうてい・かっぽう",100,0, 102,"懐石料理","かいせきりょうり",101,0, 103,"精進料理","しょうじんりょうり",101,0, 105,"会席料理","かいせきりょうり",101,0, 106,"料亭","りょうてい",101,0, 107,"割烹","かっぽう",101,0, ~略~
上記で居酒屋って言ってたのは、カテゴリ1が505って事です。
505,"居酒屋","いざかや",500,0,
海老名の居酒屋で検索して結果のファセットの詳細をみていくと、、、
1. category_id2のvalueが無いのが9件
2. category_id2が127(焼き鳥)が1件
3. category_id2が159(カニ)が1件
4. category_id2が178(和食その他)が1件
5. category_id2が502(ダイニングバー)が1件
で、唯一category_id3のデータを持ってたのが上記の5.で
category_id3が172(沖縄料理)でした。
なんか1件ばっかりで、多段にネストしないとこの検証の意味ないじゃん、、、
って事になってしまって、ちょっと微妙だったので、新宿も試してみました。
新宿&fq=category_id1:505&wt=xml&facet=true&facet.pivot=category_id1,category_id2,category_id3http://localhost:8983/solr/collection1/select?q=
新宿で居酒屋だと570件も引っかかって、
facetのとこみると、category_id3もガッツリ入ってますね~
category_id2が178でcategory_id3で718が24件って事で。
何のお店かな?って思ったら↓でした。
178,"和食その他","わしょくそのた",179,0, 718,"創作料理","そうさくりょうり",999,0,
んま、蓋を開けてみると、土間土間とかつぼ八って事でしたが、、w
<str name="id">345180</str> <str name="name">八吉</str> <str name="property">新宿三丁目店</str> <str name="id">345191</str> <str name="name">土間土間</str> <str name="property">新宿東口店</str> <str name="id">345214</str> <str name="name">つぼ八</str> <str name="property">新宿駅中央口店</str>
このデータ使ってUIも作ってキャッキャしてみるかのぅ。
#って、いつもなんだかんだでやらないんだけどww
技術評論社
売り上げランキング: 24318
コメント