SolrをPHPで使う(更新編)

前回の検索編に引き続き、今回はPHPでSolrのインデックスを更新する方法です。

更新リクエストを表すクラスは用意されていないので、XML文字列で直接更新リクエストを記述します。 commit() を実行しないとその場では反映されないので注意。

実行結果は以下の通りです。
正しくドキュメントが追加されていることが分かります。

$ php example_solr_php_update1.php 
{
  "responseHeader":{
    "rf":1,
    "status":0,
    "QTime":3}}

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":2,
    "params":{
      "q":"id:PHPUpdateTest",
      "indent":"on",
      "version":"2.2",
      "wt":"json"}},
  "response":{"numFound":1,"start":0,"numFoundExact":true,"docs":[
      {
        "id":"PHPUpdateTest",
        "name":"PHPからの更新テスト",
        "manu":"splout",
        "cat":["software",
          "search"],
        "features":["テストです。",
          "説明です。"],
        "price":1.0,
        "price_c":"1.0,USD",
        "inStock":true,
        "_version_":1734261680380051456,
        "price_c____l_ns":100}]
  }}

Solr 9をビルドする

はじめに

Solr 9 になって ant, ivy によるビルドから Gradle によるビルドに変わりました。
ソースパッケージに付属の README の手順通りではありますが、一通り手順を確認したのでまとめてみます。

JDKのバージョン

OpenJDK 11 以降が要求されています。

ソースコードの取得

ソースパッケージをダウンロードするか、git clone するかします。

$ git clone https://github.com/apache/solr.git

ビルド

ソースパッケージをダウンロードして展開したら、以下を実行します。

$ ./gradlew assemble

予め Gradle をインストールしておく必要は無く、gradlew スクリプトが必要なバージョンの Gradle をダウンロードして設定した上で実行してくれます。

ビルドが完了すると、成果物は solr/packaging/build/solr-9.0.0-SNAPSHOT 以下に作られます(solr-9.0.0-srcの場合)。 また、配布ようにパッケージングされたファイルが
solr/packaging/build/distributions/solr-9.0.0-SNAPSHOT.tgz に作られます。

起動

ここまで来ればいつも通りの solr コマンドで起動できます。

$ cd solr/packaging/build/solr-9.0.0-SNAPSHOT
$ bin/solr start -c

漫画、小説の電子書籍はhontoがおすすめ

少し前まで電子書籍は全部Kindleで買ってましたがiOSアプリのKindleでちゃんとシリーズ化されないという不満が沸々と溜まりつつも、長年続いててサービスが終わりそうにないとこはないよなぁと思って諦めてたんですが、hontoをみつけてここ一年で今までKindleで買った冊数を軽く超え(700冊以上)個人的にhontoがめっちゃおすすめだったので紹介です。

電子書籍

本の種類数で言えばKindleが圧倒的ですが自分の好んで読む漫画、小説で娯楽という観点でいくと圧倒的にhontoが便利です。2巻、3巻と続くものは特にです!

評価はiOSのタブレット版アプリについてになりますが

  • 漫画も小説もちゃんとシリーズ化される(Kindleは小説は微妙だしシリーズ化もされないものや途中の巻が抜けるものがある)
  • 読み直すときに最初から読むか続きから読むか選べる(たまに読み直したりするときに余計な手間が省かれて便利)
  • 途中まで読んだところを記録するブックマークがある(漫画は全部一気に読むが小説はたまに途中で抜けるので便利)
  • 新刊のお知らせが表示される(Kindleはたまにされないものがある)
  • お気に入りの漫画は一冊だけでシリーズ化しているものが入る(お気に入りリストとか作るのに便利)
  • 最後まで読んで次の巻があるとそのまま続きが読める(続きものを読むときに便利)
  • クーポンやポイント等お得なイベントがが頻繁に行われる

使ってて不満点としては次の巻に進むときにたまにアプリが落ちるぐらいで個人的には不満点はほぼないです。なので個人的には漫画や小説を楽しむならhontoがおすすめです!

大阪ミナミのおすすめカフェ3選

毎朝コーヒーを飲まなきゃ気がすまない私が、大阪のミナミでチャンスがあれば立ち寄るカフェを紹介します。

前回はキタ側だったので、今回は大阪のミナミ側の紹介となっています。
https://blog.splout.co.jp/11641/

タイミング悪いとなかなか入れない場合もありますが、もし近くに立ち寄ったら、ぜひ一度、覗いてみて欲しいカフェです!

①嵜本珈琲

最初にご紹介するカフェは高級食パンでも有名な「嵜本珈琲」です。
なんばパークスの隣の路地のようなところにあります。

MAP: https://tabelog.com/osaka/A2701/A270202/27122354/dtlmap/

ブレンドコーヒーが美味しく色々あるのですが特徴的なのがその名前。
・休日のブランチ
・陽だまりとひと休み
など

コーヒーイメージにぴったりな名前やイラストがついています。

向かいには「嵜本ベーカリーカフェ」があり、オーガニックな雰囲気の中、美味しいパンとコーヒーが楽しめます。

②OSARU COFFEE

続いて紹介するのは、おさるさんのロゴが可愛い「OSARU COFFEE」です。
JR難波の近くにあります。

MAP: https://tabelog.com/osaka/A2701/A270202/27093851/dtlmap/

落ち着いた店内でスペシャルティコーヒーやスイーツを楽しむことができます。
靴を脱いでゆったりくつろぐことができるのですが席数が少ないのでなかなか座れないかも…。

そんなときは、お持ち帰りもあるので、お好きな味のスペシャルティコーヒーが選んで、近くの公園とかでゆったりするのもありです。
コップのロゴもやっぱりかわいい。

③エルマーズグリーン インザパーク

最後に紹介するのは、「エルマーズグリーンカフェ インザパーク」です。
なんばパークスの3階にあります。

MAP: https://tabelog.com/osaka/A2701/A270202/27084285/dtlmap/

こちらも丁寧にドリップされた、スペシャルティコーヒーを飲むことができます。
こちらに立ち寄ったときは、ソフトクリームもおすすめで、甘すぎず上品なミルク風味でこれからの暑い季節にぴったりです!

いかがでしょうか?まだまだ紹介したいお店はあるのですが、大阪のミナミのカフェを3つ紹介しました。カフェ選びの参考になれば幸いです。

SolrをPHPで使う(検索編)

前回の記事でSolrをPHPから使う準備ができました。
今回はPHPで Solr の検索を実行する方法です。

検索結果のオブジェクトは以下のような構造になっています。

SolrObject Object
(
    [responseHeader] => SolrObject Object
        (
            [zkConnected] => 1
            [status] => 0
            [QTime] => 0
            [params] => SolrObject Object
                (
                    [q] => *:*
                    [indent] => on
                    [start] => 0
                    [rows] => 2
                    [version] => 2.2
                    [wt] => xml
                )

        )

    [response] => SolrObject Object
        (
            [numFound] => 52
            [start] => 0
            [docs] => Array
                (
                    [0] => SolrDocument Object
                        (
                            [_hashtable_index:SolrDocument:private] => 24804
                        )

                    [1] => SolrDocument Object
                        (
                            [_hashtable_index:SolrDocument:private] => 5340
                        )

                )

        )

)

docs という配列の要素である SolrDocument オブジェクトは SolrDocumentField オブジェクトを複数含んでいます。SolrDocument 内のすべての SolrDocumentField をたどるために current() や next() などのメソッドを利用します。

SolrObject ベースの検索結果は意外と扱いづらいので、JSON で扱えるようにしてみます。

SolrClient 作成時のオプションとして wt=json を追加しています。

getRawResponse() の応答は以下の通りです。

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"*:*",
      "indent":"on",
      "start":"0",
      "rows":"2",
      "version":"2.2",
      "wt":"json"}},
  "response":{"numFound":52,"start":0,"numFoundExact":true,"docs":[
      {
        "id":"0553573403",
        "cat":["book"],
        "name":"A Game of Thrones",
        "price":7.99,
        "price_c":"7.99,USD",
        "inStock":true,
        "author":"George R.R. Martin",
        "author_s":"George R.R. Martin",
        "series_t":"A Song of Ice and Fire",
        "sequence_i":1,
        "genre_s":"fantasy",
        "_version_":1730974266238697472,
        "price_c____l_ns":799},
      {
        "id":"0553579908",
        "cat":["book"],
        "name":"A Clash of Kings",
        "price":7.99,
        "price_c":"7.99,USD",
        "inStock":true,
        "author":"George R.R. Martin",
        "author_s":"George R.R. Martin",
        "series_t":"A Song of Ice and Fire",
        "sequence_i":2,
        "genre_s":"fantasy",
        "_version_":1730974266279591936,
        "price_c____l_ns":799}]
  }}

これを json_decode() することで、通常の PHP 配列として扱うことができます。

Array
(
    [responseHeader] => Array
        (
            [zkConnected] => 1
            [status] => 0
            [QTime] => 0
            [params] => Array
                (
                    [q] => *:*
                    [indent] => on
                    [start] => 0
                    [rows] => 2
                    [version] => 2.2
                    [wt] => json
                )

        )

    [response] => Array
        (
            [numFound] => 52
            [start] => 0
            [numFoundExact] => 1
            [docs] => Array
                (
                    [0] => Array
                        (
                            [id] => 0553573403
                            [cat] => Array
                                (
                                    [0] => book
                                )

                            [name] => A Game of Thrones
                            [price] => 7.99
                            [price_c] => 7.99,USD
                            [inStock] => 1
                            [author] => George R.R. Martin
                            [author_s] => George R.R. Martin
                            [series_t] => A Song of Ice and Fire
                            [sequence_i] => 1
                            [genre_s] => fantasy
                            [_version_] => 1730974266238697472
                            [price_c____l_ns] => 799
                        )

                    [1] => Array
                        (
                            [id] => 0553579908
                            [cat] => Array
                                (
                                    [0] => book
                                )

                            [name] => A Clash of Kings
                            [price] => 7.99
                            [price_c] => 7.99,USD
                            [inStock] => 1
                            [author] => George R.R. Martin
                            [author_s] => George R.R. Martin
                            [series_t] => A Song of Ice and Fire
                            [sequence_i] => 2
                            [genre_s] => fantasy
                            [_version_] => 1730974266279591936
                            [price_c____l_ns] => 799
                        )

                )

        )

)