Faire des recherches dans un index SOLR
Me voila avec un index flambant neuf ( ou presque) importé en presque 30 minutes. Je n'ai plus qu'à rechercher. Voici ce qu'on peut faire assez simplement "out of the box":
Via l'interface d'administration
L'interface d'administration possède déjà un outil de recherche assez simple d'utilisation. On renseigne le critère de recherche et on obtient la réponse au format souhaité ( JSON, XML, PYTHON, CSV,...)
Cette option peut être intéressante pour une interface d'administration
Via une requête REST
J'ai fait un simple appel REST avec JERSEY pour effectuer la même requête. J'ai utilisé le mapping des POJO pour mapper la réponse à mon bean.
On retrouve les mêmes paramètres
public class RESTQueryTest { public static final int HTTP_STATUS_OK = 200; private Client client; private WebResource queryWebResource; private ClientConfig clientConfig; @Before clientConfig = new DefaultClientConfig(); client = Client.create(clientConfig); queryWebResource = client.resource(QUERY_URL); } @Test MultivaluedMap<String, String> parameters = new MultivaluedMapImpl(); parameters.add("q", "lastname:JAN"); parameters.add("wt", "json"); ClientResponse response = queryWebResource.queryParams(parameters).type(MediaType.TEXT_PLAIN_TYPE). accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE).get(ClientResponse.class); assertEquals(response.getStatus(), HTTP_STATUS_OK); } @Test MultivaluedMap<String, String> parameters = new MultivaluedMapImpl(); parameters.add("q", FUZZY_QUERY_BY_LASTNAME); parameters.add("wt", "json"); parameters.add("indent", "true"); final int MAX_ROWS = 20; ClientResponse response = queryWebResource.queryParams(parameters).type(MediaType.APPLICATION_JSON_TYPE). accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE).get(ClientResponse.class); assertEquals(response.getStatus(), HTTP_STATUS_OK); SOLRResponse<CustomerResource> solrResponse=response.getEntity(new GenericType<SOLRResponse<CustomerResource>>(){}); assertNotNull(solrResponse); assertEquals(solrResponse.getResponse().getDocs().size(), MAX_ROWS); assertEquals(solrResponse.getResponseHeader().getParams().getQuery(),FUZZY_QUERY_BY_LASTNAME); } }
La classe SOLRResponse
décrit la réponse JSON, Elle est annotée avec JAXB.
@XmlRootElement public class SOLRResponse<T> { private SOLRResponseHeader responseHeader ; private SOLRResponseBody<T> response; public SOLRResponseBody<T> getResponse() { return response; } public void setResponse(SOLRResponseBody<T> response) { this.response = response; } public SOLRResponseHeader getResponseHeader() { return responseHeader; } public void setResponseHeader(SOLRResponseHeader responseHeader) { this.responseHeader = responseHeader; } }
J'ai rendu cette réponse générique pour ensuite appliquer ce que l'on veut dans les documents (ex. Classe CustomerResource
)
Via l'API SOLRJ
Pré-requis
Ajouter la dépendance solr au projet
<dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> <version>${solr.version}</version> </dependency>
Je trouve cette solution beaucoup plus simple à mettre en oeuvre. Elle prend dynamiquement les champs de la réponse ( qui peuvent changer selon les paramètres d'appels ). De plus il n'y a pas besoin de décrire l'enveloppe de la réponse comme en REST.
public class JavaQueryTest { private HttpSolrServer solrServer; private SolrQuery solrQuery; @Before solrServer = new HttpSolrServer(QUERY_URL); solrServer.setAllowCompression(true); solrServer.setMaxRetries(5); solrQuery = new SolrQuery(); } @Test solrQuery.setQuery("TOURET~"); solrQuery.addSort("dtcrea", SolrQuery.ORDER.asc); QueryResponse response = solrServer.query(solrQuery); assertNotNull(response); assertNotNull(response.getResults()); assertFalse(response.getResults().isEmpty()); List<CustomerResource> customers = response.getBeans(CustomerResource.class); assertNotNull(customers); assertFalse(customers.isEmpty()); } }