け日記

最近はPythonでいろいろやってます

Solrで検索 (フィルタ, ソート, ファセット, ハイライト)

前回・前々回に引き続いて、Solrについてです。

今回は検索クエリで頻繁に使われる、フィルタ、ソート、ファセット、ハイライトについてまとめます。引き続き、チュートリアルと↓の本を参考にしています。

[改訂第3版]Apache Solr入門――オープンソース全文検索エンジン (Software Design plus)

なお、前々回のSolrのダウンロード、前回のkenikkiコレクションの追加まで完了している状態を前提として進めます。

ohke.hateblo.jp

ohke.hateblo.jp

フィルタ

レスポンスで返す属性を限定する場合は、flを使います。

urlとtitleのみが欲しい場合、fl=url,titleとします。

http://localhost:8983/solr/kenikki/select?fl=url,title&q=*:*&rows=2&sort=published_datetime desc
[
    {
        "url":"https://ohke.hateblo.jp/entry/2018/11/17/230000",
        "title":"Python: LexRankで日本語の記事を要約する - け日記"
    },
    {
        "url":"https://ohke.hateblo.jp/entry/2018/11/10/230000",
        "title":"SQL ServerのテーブルをPandas DataFrameで読み書きする - け日記"
    }
]

ソート

特定のフィールドにマッチする場合に検索結果 (ランキング) の上位に持ってくる、などのソートはqfを使います。

例えばcontentを"協調フィルタリング"で検索すると以下のような結果が返ってきます。

http://localhost:8983/solr/kenikki/select?facet=on&fl=title&q=content:協調フィルタリング&rows=5
[
    { "title":"「Context-Aware Recommender Systems」まとめ - け日記" },
    { "title":"Pythonでレコメンドシステムを作る(ユーザベース協調フィルタリング) - け日記" },
    { "title":"Pythonでレコメンドシステムを作る(アイテムベース協調フィルタリング) - け日記" },
    { "title":"論文メモ: Item2Vec: Neural Item Embedding for Collaborative Filtering - け日記" },
    { "title":"Pythonでレコメンドシステムを作る(コンテンツベースフィルタリング) - け日記" }
]

もし大小が比較できる特定のフィールドでソートするなら、sortクエリパラメータでOKです。例えば、公開日付の降順であれば、以下のようにすれば最新5件が取得できます。

http://localhost:8983/solr/kenikki/select?fl=url,title&q=content:協調フィルタリング&rows=5&sort=published_datetime desc

テキストフィールドに限った、もう少し細かいケースを考えてみます。
検索文字列がtitleに入っているエントリの方が上位にランクインしやすくなってほしいなどの場合、qfが使えます。
例えば、qf=title^2 content^1とすると、titleの重みがcontentの重みよりも大きくする (ここでは2倍) ことで、上に来やすくなります。

http://localhost:8983/solr/kenikki/select?defType=dismax&fl=title&q=content:協調フィルタリング&qf=title^2 content^1&rows=5

結果としては、タイトルに"協調フィルタリング"を含むエントリが上位にランクインしやすくなりました。
あくまでソート時の重み付けですので、タイトルに検索文字列を含んでいなかったとしても、結果から除外されることはありません。
また、contentの重みも有効ですので、常にタイトルに文字列を含んでいるエントリが上に来るとは限りません。現に、下の結果ではタイトルにフィルタリングを含むエントリが、含まないエントリの下に来ています。常に上に持ってきたい場合は qf=title^100 content^1 などの極端な重み付けを行うと良いです。

[
    { "title":"Pythonでレコメンドシステムを作る(ユーザベース協調フィルタリング) - け日記" },
    { "title":"Pythonでレコメンドシステムを作る(アイテムベース協調フィルタリング) - け日記" },
    { "title":"「Context-Aware Recommender Systems」まとめ - け日記" },
    { "title":"Pythonでレコメンドシステムを作る(コンテンツベースフィルタリング) - け日記" },
    { "title":"論文メモ: Item2Vec: Neural Item Embedding for Collaborative Filtering - け日記" }
]

ファセット

クエリでの検索結果からさらに絞り込むために、カテゴリごとの件数を表示したい、というケースがあるかと思います。そうしたケースに使えるのがファセットです。

tagごとの件数を取得する場合、以下のようにfacet.field=tagで指定します。

http://localhost:8983/solr/kenikki/select?facet.field=tag&facet=on&fl=url,title&q=content:協調フィルタリング&rows=1&sort=published_datetime desc

そうすると、facet_counts.facet_fields.tagに各tagの件数がセットされて返ってきます。

{
  "responseHeader":{...},
  "response":{"numFound":7,"start":0,"docs":[
      {
        "url":"https://ohke.hateblo.jp/entry/2018/06/02/230000",
        "title":"Google AnalyticsのデータをBigQueryで集計・分析するときのテクニック集 - け日記"}]
  },
  "facet_counts":{
    "facet_queries":{},
    "facet_fields":{
      "tag":[
        "Recommender system",5,
        "Python",4,
        "BigQuery",1,
        "Google Analytics",1,
        "NLP",1,
        "読書メモ",1,
        "論文メモ",1,
        ".NET Core",0,
        "ASP.NET",0,...
    ]},
    "facet_ranges":{},
    "facet_intervals":{},
    "facet_heatmaps":{}}}

ハイライト

クエリとマッチした箇所を検索結果で強調表示したい時があるかと思います。Solrにはハイライトという機能で提供されてます。

以下のクエリではtitleとdescriptionをハイライトします。2つのパラメータを渡してます。

  • hl=onとすることで、ハイライトを有効化
  • hl.fl=title,descriptionとすることで、ハイライト表示するフィールドを設定
http://localhost:8983/solr/kenikki/select?fl=title&hl.fl=title,description&hl=on&q=content:Python&rows=2

hilightingにハイライト表示に関する結果が入ってます。
response.docsに対応するディクショナリとなっており、キーはidフィールドで、値はフィールドごとにemタグで強調表示加工されていることがわかります。

  • emタグはhl.simple.prehl.simple.postに値を渡すことによって、別の文字列に置き換えることができます
    • 例えばhl.simple.pre=<u>&hl.simple.post=</u>とすると、uタグになります
{
  "responseHeader":{...},
  "response":{
    "numFound":56,
    "start":0,
    "docs":[
      { "title":"Visual Studio CodeでFlaskをデバッグする環境を作る on Mac - け日記" },
      { "title":"PythonでGoogle AnalyticsのデータをPostgreSQLへロードする - け日記" }
    ]
  },
  "highlighting":{
    "19f44dde-ec88-46f6-b629-6e813d552016":{
      "description":["仕事でFlaskを使ったアプリケーションを作る機会があり、Visual Studio Code(VSCode)で環境を整えましたので、その備忘録です。 前提 VS Code、<em>Python</em>、Flask"]
    },
    "8a19d435-0cc5-44da-9bc1-a38e440db4fe":{
      "title":["<em>Python</em>でGoogle AnalyticsのデータをPostgreSQLへロードする - け日記"],
      "description":["Google Analytics(GA)のデータを機械学習の勉強用に使えないかなと思ったことがきっかけです。 まずは、<em>Python</em>で扱いやすくするために、GAのデータをローカルのPostgreSQL"]
    }
  }
}

まとめ

今回はSolrでよく使うクエリとして、フィルタ、ソート、ファセット、ハイライトについて整理しました。

参考文献

[改訂第3版]Apache Solr入門――オープンソース全文検索エンジン (Software Design plus)

[改訂第3版]Apache Solr入門――オープンソース全文検索エンジン (Software Design plus)

  • 作者: 打田智子,大須賀稔,大杉直也,西潟一生,西本順平,平賀一昭,株式会社ロンウイット,株式会社リクルートテクノロジーズ
  • 出版社/メーカー: 技術評論社
  • 発売日: 2017/04/27
  • メディア: 大型本
  • この商品を含むブログを見る