SolrJを使ってSolr検索をする

エキサイト株式会社の武藤です。

エキサイトホールディングス Advent Calendar 2021の18日目の記事です。

qiita.com

今回は、Spring Boot プロジェクトでSolrJを使ってSolr検索を実装する手順について説明します。

SolrJ

SolrのJava用のAPIです。 solr.apache.org

Spring Bootには、Solr用のSpring Dataがありますが、新規プロジェクトへの利用は非推奨です。

spring.io

This project is about to move to the Spring Attic and is not recommended for new projects. The last Release (4.3.0) will, as part of the spring data release 2020.0, see patch updates till mid 2022.

そういった経緯もあり、今回はSolrJを採用しました。

実装

build.gradle に下記の行を追加します。

implementation "org.apache.solr:solr-solrj:x.xx.x" 

SolrスキーマJavaで定義します。

@Fieldスキーマのフィールド名からJavaのプロパティーへの変換を設定します。

@Data
public class BookSolrModel {

    @Field("book_id")
    private String bookId;

    @Field
    private String name;

    @Field
    private String description;
}

次に、リクエストからレスポンスの取得です。Spring BootのRepository層での実装例です。

SolrQueryをインスタンス化し、クエリーをセットします。

Solrから取得したBookSolrModelをドメインモデルにマッピングしています。

HttpSolrClient.query()はThrowableなので、例外ハンドリングをしています。

@Repository
@RequiredArgsConstructor
public class BookRepositoryImpl implements BookRepository {

    private final HttpSolrClient httpSolrClient;

    @Override
    public List<BookModel> getBookList(String bookId) {
        try {
            final SolrQuery query = new SolrQuery();
            query
                    .setQuery("book_id:" + bookId)
                    .setStart(0)
                    .setRows(1);

            final QueryResponse response = httpSolrClient.query(query);

            final List<BookSolrModel> bookSolrModelList = httpSolrClient
                    .getBinder()
                    .getBeans(BookSolrModel.class, response.getResults());

            return bookSolrModelList
                    .stream()
                    .map(bookSolrModel ->
                            new BookModel()
                                    .setBookId(bookSolrModel.getBookId())
                                    .setName(bookSolrModel.getName())
                                    .setDescription(bookSolrModel.getDescription())
                    )
                    .collect(Collectors.toList());

        } catch (SolrServerException | IOException e) {
            return List.of();
        }
    }
}

HttpSolrClientは @Bean によりDIコンテナに登録することで、他のRepositoryでもインスタンスを使い回せるようにしています。

Solrのホストはapplication.yml で定義しておき、 @Value で呼び出します。これにより環境の差異をコードに記載しなくて済みます。

@Configuration
public class SolrConfig {
    @Value("${solr.host}")
    private String solrHost;

    @Bean
    public HttpSolrClient httpSolrClient() {
        return new HttpSolrClient.Builder(solrHost).build();
    }
}

類似要素検索

MoreLikeThisを使った類似検索の例です。

            final SolrQuery query = new SolrQuery();
            query
                    .setQuery("book_id:" + bookId)
                    .setStart(0)
                    .setRows(1)
                    .setMoreLikeThis(true)
                    .setMoreLikeThisFields("name")
                    .setMoreLikeThisCount(3);

            final QueryResponse response = httpSolrClient.query(query);

            final List<BookSolrModel> bookSolrModelList = httpSolrClient
                    .getBinder()
                    .getBeans(BookSolrModel.class, response.getMoreLikeThis().get(bookId));

最後に

簡単にですが、Spring BootプロジェクトでのSolrJの使い方について説明しました。 他の言語で提供されているSolr APIと大きな差はなく、使いやすいものでした。 参考になれば幸いです。

エキサイトでは、エンジニア募集を随時行っております。 www.wantedly.com

引き続きエキサイトホールディングスのアドベントカレンダーをお楽しみいただければ幸いです。 qiita.com

参考

solr.apache.org