I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

Apache Solr is an open-source search platform built on top of Lucene. Apache SolrJ is a Java-based client for Solr that provides interfaces for the main features of search like indexing, querying, and deleting documents.

In this article, we’re going to explore how to interact with an Apache Solr server using SolrJ.

2. Setup

In order to install a Solr server on your machine, please refer to the Solr QuickStart Guide.

The installation process is simple — just download the zip/tar package, extract the contents, and start the server from the command line. For this article, we’ll create a Solr server with a core called ‘bigboxstore’:

bin/solr start
bin/solr create -c 'bigboxstore'

By default, Solr listens to port 8983 for incoming HTTP queries. You can verify that it is successfully launched by opening the http://localhost:8983/solr/#/bigboxstore URL in a browser and observing the Solr Dashboard.

3. Maven Configuration

Now that we have our Solr server up and running, let’s jump straight to the SolrJ Java client. To use SolrJ in your project, you will need to have the following Maven dependency declared in your pom.xml file:

<dependency>
    <groupId>org.apache.solr</groupId>
    <artifactId>solr-solrj</artifactId>
    <version>6.4.0</version>
</dependency>

You can always find the latest version hosted by Maven Central.

4. Apache SolrJ Java API

Let’s initiate the SolrJ client by connecting to our Solr server:

String urlString = "http://localhost:8983/solr/bigboxstore";
HttpSolrClient solr = new HttpSolrClient.Builder(urlString).build();
solr.setParser(new XMLResponseParser());

Note: SolrJ uses a binary format, rather than XML, as its default response format. For compatibility with Solr, it’s required to explicitly invoke setParser() to XML as shown above. More details on this can be found here.

4.1. Indexing Documents

Let’s define the data to be indexed using a SolrInputDocument and add it to our index using the add() method:

SolrInputDocument document = new SolrInputDocument();
document.addField("id", "123456");
document.addField("name", "Kenmore Dishwasher");
document.addField("price", "599.99");
solr.add(document);
solr.commit();

Note: Any action that modifies the Solr database requires the action to be followed by commit().

4.2. Indexing with Beans

You can also index Solr documents using beans. Let’s define a ProductBean whose properties are annotated with @Field:

public class ProductBean {

    String id;
    String name;
    String price;

    @Field("id")
    protected void setId(String id) {
        this.id = id;
    }

    @Field("name")
    protected void setName(String name) {
        this.name = name;
    }

    @Field("price")
    protected void setPrice(String price) {
        this.price = price;
    }

    // getters and constructor omitted for space
}

Then, let’s add the bean to our index:

solrClient.addBean( new ProductBean("888", "Apple iPhone 6s", "299.99") );
solrClient.commit();

4.3. Querying Indexed Documents by Field and Id

Let’s verify our document is added by using SolrQuery to query our Solr server.

The QueryResponse from the server will contain a list of SolrDocument objects matching any query with the format field:value. In this example, we query by price:

SolrQuery query = new SolrQuery();
query.set("q", "price:599.99");
QueryResponse response = solr.query(query);

SolrDocumentList docList = response.getResults();
assertEquals(docList.getNumFound(), 1);

for (SolrDocument doc : docList) {
     assertEquals((String) doc.getFieldValue("id"), "123456");
     assertEquals((Double) doc.getFieldValue("price"), (Double) 599.99);
}

A simpler option is to query by Id using getById(). which will return only one document if a match is found:

SolrDocument doc = solr.getById("123456");
assertEquals((String) doc.getFieldValue("name"), "Kenmore Dishwasher");
assertEquals((Double) doc.getFieldValue("price"), (Double) 599.99);

4.4. Deleting Documents

When we want to remove a document from the index, we can use deleteById() and verify it has been removed:

solr.deleteById("123456");
solr.commit();
SolrQuery query = new SolrQuery();
query.set("q", "id:123456");
QueryResponse response = solr.query(query);
SolrDocumentList docList = response.getResults();
assertEquals(docList.getNumFound(), 0);

We also have the option to deleteByQuery(), so let’s try deleting any document with a specific name:

solr.deleteByQuery("name:Kenmore Dishwasher");
solr.commit();
SolrQuery query = new SolrQuery();
query.set("q", "id:123456");
QueryResponse response = solr.query(query);
SolrDocumentList docList = response.getResults();
assertEquals(docList.getNumFound(), 0);

5. Conclusion

In this quick article, we’ve seen how to use the SolrJ Java API to perform some of the common interactions with the Apache Solr full-text search engine.

You can check out the examples provided in this article over on GitHub.

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS