Apache Solrで使える便利な検索の紹介

1.5K Views

March 10, 24

スライド概要

※PHPerKaigi 2024で発表したときに利用したスライドです。

Apache Solr(以後Solr)という名前を聞いたことがある人は全文検索用に使うやつでしょ?というイメージが強いのではないかと思います。

Solrは全文検索だけではありません。なかなかイケてる検索もできます。

ちなみにSolrの読み方は「ソーラー」です。

profile-image

ITエンジニアやっています。LaravelとVueがメインの戦場。最近はSolrとも戦っています。 花火好きなのでよく観に行きます。花火鑑賞士試験にも合格してたりします。 あとゲームマーケットでボドゲを出展してて、今までの題材は花火とITとオーロラです。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

(ダウンロード不可)

関連スライド

各ページのテキスト
1.

Apache Solrで使える便利な検索の紹介 PHPerKaigi 2024 3/8 @masnmt littlehermit LLC.

2.

自己紹介 @masnmt (読み方はますんと) 合同会社リトルハーミットの代表やってる野本といいます。 花火を観るのが好きで、花火鑑賞士試験に合格してたりもします。 あと、ボドゲとお酒も好きです。 好きなディストリビューション Debian GNU/Linux 好きなエディタ GNU Emacs 好きなDBMS PostgreSQL メインブラウザ Vivaldi 好きなポインティングデバイス トラックボール IMEの日本語入力方式 かな入力 主な戦場 PHP Laravel フロントエンド Vue クラウド AWS

3.

自己紹介 こんなボドゲ作ってたりします。 まけるな! あいすいー えんじにあ 迫りくる納期と戦う ITエンジニアの 苦悩がここに! たたかえ! あいすいー えんじにあ 大惨事を隠蔽しつつ 登録ユーザ数を 伸ばせ!

4.

Apache Solrって何?

5.

Apache Solrって何? オープンソースの全文検索システムです。 非常に高速で、大量の文字データを扱うことに長けています。 ちなみに読み方は「そーらー」です。 内部エンジンはElasticsearchと同じものを利用しています。

6.

Apache Solrって何? DBでいうところのレコードはSolrではドキュメントといいます。 DBでいうところの列はフィールドといいます。 条件の指定方法の対比 SQL Solr WHERE hoge = 'abc' q:"hoge:abc" WHERE 地域 = '関東' AND 打上発数 >= 10000 q:"地域:関東 AND 打上発数:[10000 TO *]"

7.

Apache Solrって何? スキーマ設計についてはLTではとても話せないので割愛・・・ 全文検索するときのメジャーの手法であるN-gramや形態素解析を利用することができます。 さらにフィルター処理をしてSolrに格納しておくことで、あいまい検索なこともできます。 検索文字列 ヒットする文字列 スターマイン スターマイン すたーまいん スターマイン 1234 1234 1234 ①②③④

8.

でも、Solrは 全文検索だけではない 知ってほしい 便利な型があります

9.

知ってほしい便利な型があります ・マルチフィールド(配列みたいなもの) ・日時の範囲 ・日時の範囲のマルチフィールド

10.

マルチフィールド (配列みたいなもの)

11.

マルチフィールド(配列みたいなもの) DBでは配列的なものを表現するために、2つのテーブルを用意します。 今回は以下のような「花火のプログラム」「玉の内容」テーブルを例にします。 花火のプログラム (DB) ID 演目 1 尺玉3発 2 5号、7号、10号 3段打ち ... ... 玉の内容 (DB) ID 花火ID 玉名 1 1 菊 2 1 牡丹 3 1 昇曲導付変化菊八重芯金閃冠 ... ... ...

12.

マルチフィールド(配列みたいなもの) 花火のプログラム (Solr) ID 演目 玉名(マルチフィールド) 1 尺玉3発 [ "菊", "牡丹", "昇曲導付変化菊八重芯金閃冠" ] 2 5号、7号、10号 3段打ち [ "銀菊", "変化菊", "彩色千輪" ] という簡潔な形で格納されます。

13.

マルチフィールド(配列みたいなもの) 右のように、玉の号数が格納されている マルチフィールドがあるとします。 演目 号数 (マルチフィールド) ... [3, 4, 7] ... [5, 10, 20, 40] ・3が入っているドキュメントが欲しい・・・ ・5と10が入っているドキュメントが欲しい・・・ ・20〜50が1つ以上入っているドキュメントが欲しい・・・ どんな書式で指定すればいいでしょうか??

14.

マルチフィールド(配列みたいなもの) SQLだとこうなりますよね? SELECT * FROM 花火 WHERE EXISTS ( SELECT * FROM 玉 WHERE 玉.花火ID = 花火.ID AND 玉.号数 = 3 ) SELECT * FROM 花火 WHERE EXISTS ( SELECT 玉.花火ID FROM 玉 WHERE 玉.花火ID = 花火.ID AND 玉.号数 IN (5,10) GROUP BY 玉.花火ID HAVING COUNT(玉.花火ID) >= 2 ) SELECT * FROM 花火 WHERE EXISTS ( SELECT 玉.花火ID FROM 玉 WHERE 玉.花火ID = 花火.ID AND 玉.号数 BETWEEN 20 AND 50 )

15.

マルチフィールド(配列みたいなもの) Solrではこうです 3が入っているドキュメントが欲しい・・・ → q:"号数:3" 5と10が入っているドキュメントが欲しい・・・ → q:"号数:(5 AND 10)" 20〜80が入っているドキュメントが欲しい・・・ → q:"号数:[20 TO 50]"

16.

日時の範囲

17.

日時の範囲 DBでは日時の範囲を表現するために、開始と終了の2つの列を用意します。 花火大会 (DB) ID 大会名 開始 終了 1 長岡まつり大花火大会 2024-08-02 2024-08-03 2 松江水郷祭湖上花火大会 2024-08-03 2024-08-04 ... ... ... ... ※Solrでは時刻まで指定する必要がありますが、本LTでは省略します。

18.

日時の範囲 花火大会 (Solr) ID 名前 期間 1 長岡まつり大花火大会 [2024-08-02 TO 2024-08-03] ・2024-08-02が入っているドキュメントが欲しい・・・ ・2024-08-01〜2024-08-31と一部でも重なるドキュメントが欲しい・・・ ・2024-08-02〜2024-08-03が完全に含まれるドキュメントが欲しい・・・ どんな書式で指定すればいいでしょうか??

19.

日時の範囲 SQLだとこうなりますよね? 2024-08-02が入っているドキュメントが欲しい・・・ → SELECT * FROM 花火大会 WHERE 開始 <= '2024-08-02' AND 終了 >= '2024-08-02' 2024-08-01〜2024-08-31と一部でも重なるドキュメントが欲しい・・・ → SELECT * FROM 花火大会 WHERE 開始 <= '2024-08-31' AND 終了 >= '2024-08-01' 2024-08-02〜2024-08-03が完全に含まれるドキュメントが欲しい・・・ → SELECT * FROM 花火大会 WHERE 開始 <= '2024-08-02' AND 終了 >= '2024-08-03'

20.

日時の範囲 Solrではこうです 2024-08-02が入っているドキュメントが欲しい・・・ → q:"期間:`2024-08-02`" 2024-08-01〜2024-08-31と一部でも重なるドキュメントが欲しい・・・ → q:"期間:`[2024-08-01 TO 2024-08-31]`" 2024-08-02〜2024-08-03が完全に含まれるドキュメントが欲しい・・・ → q:"!{field f=期間 op=Contains}`[2024-08-02 TO 2024-08-03]`"

21.

日時の範囲の マルチフィールド

22.

日時の範囲のマルチフィールド DBで日時の範囲を表現するために、2つの列を用意します。 今回は以下のような「花火大会」「期間」テーブルを例にします。 花火大会 (DB) ID 演目 1 長岡まつり大花火大会 2 片貝まつり 浅原神社秋季例大祭奉納大煙火 ... ... 期間 (DB) ID 花火大会 ID 開始 終了 1 1 2024-08-02 2024-08-03 2 1 2023-08-02 2023-08-03 3 2 2024-09-09 2024-09-10 ... ... ... ...

23.

日時の範囲のマルチフィールド 花火大会 (Solr) 演目 期間 (開始 終了)のマルチフィールド 長岡まつり大花火大会 [[2023-08-02 TO 2023-08-03], [2024-08-02 TO 2024-08-03]] ・2024-08-02が入っているドキュメントが欲しい・・・ ・2024-08-01〜2024-08-31と一部でも重なるドキュメントが欲しい・・・ ・2024-08-02〜2024-08-03が完全に含まれるドキュメントが欲しい・・・ どんな書式で指定すればいいでしょうか??

24.

日時の範囲のマルチフィールド SQLだとこうなりますよね? SELECT * FROM 花火大会 WHERE EXISTS ( SELECT * FROM 期間 WHERE 期間.花火大会ID = 花火大会.ID AND 期間.開始 <= '2024-08-02' AND 期間.終了 >= '2024-08-02' ) SELECT * FROM 花火大会 WHERE EXISTS ( SELECT * FROM 期間 WHERE 期間.花火大会ID = 花火大会.ID AND 期間.開始 <= '2024-08-31' AND 期間.終了 >= '2024-08-01' ) SELECT * FROM 花火大会 WHERE EXISTS ( SELECT * FROM 期間 WHERE 期間.花火大会ID = 花火大会.ID AND 期間.開始 <= '2024-08-02' AND 期間.終了 >= '2024-08-03' )

25.

日時の範囲のマルチフィールド 日時の範囲のときと 全く同じ書式でいいんです! → q:"期間:`2024-08-02`" → q:"期間:`[2024-08-01 TO 2024-08-31]`" → q:"!{field f=期間 op=Contains}`[2024-08-02 TO 2024-08-03]`"

26.

でも、 この便利な型たちって もしかして…

27.

そう、PostgreSQLなら 全て実装されています!

28.

Solrだと 嬉しいことってないの…?

29.

Solrだと嬉しいことってないの…? SELECT * FROM 花火 WHERE EXISTS (SELECT * FROM 玉 …) みたいなSQLだと、玉の情報も欲しいならもう1回SELECTしないといけないですよね? あと、条件に適合する全件数も欲しいなら、さらにSELECT COUNT(*)しないと取れないですよね?? Solrは1回のリクエストで全部取得することができます!

30.

まとめ 全文検索とか、日付の範囲を大量に扱うような用途では Solrだと便利な絞り込みがたくさん使えるし、レスポンス も高速なので興味がある方は一度触ってみてはいかか?

31.

ご清聴ありがとうございました Thank you for listening! @masnmt littlehermit LLC.