Faire des recherches dans un index SOLR

2561885967_f5f0be5834_n.jpgMe 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,...)

backup_sonar036.png

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

  1. public class RESTQueryTest {
  2.  
  3. private final static String QUERY_URL = "http://127.0.0.1:8080/customers/customers/select";
  4. public static final int HTTP_STATUS_OK = 200;
  5. private Client client;
  6. private WebResource queryWebResource;
  7. private ClientConfig clientConfig;
  8. private String MAX_ROWS;
  9.  
  10. @Before
  11. public void setUp() throws Exception {
  12. clientConfig = new DefaultClientConfig();
  13. clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
  14. client = Client.create(clientConfig);
  15. queryWebResource = client.resource(QUERY_URL);
  16. }
  17.  
  18. @Test
  19. public void testQueryByLastName() throws Exception {
  20. MultivaluedMap<String, String> parameters = new MultivaluedMapImpl();
  21. parameters.add("q", "lastname:JAN");
  22. parameters.add("wt", "json");
  23.  
  24. ClientResponse response = queryWebResource.queryParams(parameters).type(MediaType.TEXT_PLAIN_TYPE).
  25. accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE).get(ClientResponse.class);
  26. assertEquals(response.getStatus(), HTTP_STATUS_OK);
  27. }
  28.  
  29. @Test
  30. public void testQueryFuzzy() throws Exception {
  31. MultivaluedMap<String, String> parameters = new MultivaluedMapImpl();
  32. final String FUZZY_QUERY_BY_LASTNAME = "lastname:JAN~";
  33. parameters.add("q", FUZZY_QUERY_BY_LASTNAME);
  34. parameters.add("wt", "json");
  35. parameters.add("indent", "true");
  36. final int MAX_ROWS = 20;
  37. parameters.add("rows", String.valueOf(MAX_ROWS));
  38.  
  39. ClientResponse response = queryWebResource.queryParams(parameters).type(MediaType.APPLICATION_JSON_TYPE).
  40. accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE).get(ClientResponse.class);
  41. assertEquals(response.getStatus(), HTTP_STATUS_OK);
  42. SOLRResponse<CustomerResource> solrResponse=response.getEntity(new GenericType<SOLRResponse<CustomerResource>>(){});
  43. assertNotNull(solrResponse);
  44. assertEquals(solrResponse.getResponse().getDocs().size(), MAX_ROWS);
  45. assertEquals(solrResponse.getResponseHeader().getParams().getQuery(),FUZZY_QUERY_BY_LASTNAME);
  46. }
  47. }

La classe SOLRResponse décrit la réponse JSON, Elle est annotée avec JAXB.

  1. @XmlRootElement
  2. public class SOLRResponse<T> {
  3.  
  4. private SOLRResponseHeader responseHeader ;
  5. private SOLRResponseBody<T> response;
  6.  
  7. public SOLRResponseBody<T> getResponse() {
  8. return response;
  9. }
  10.  
  11. public void setResponse(SOLRResponseBody<T> response) {
  12. this.response = response;
  13. }
  14.  
  15. public SOLRResponseHeader getResponseHeader() {
  16. return responseHeader;
  17. }
  18.  
  19. public void setResponseHeader(SOLRResponseHeader responseHeader) {
  20. this.responseHeader = responseHeader;
  21. }
  22.  
  23.  
  24. }

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

  1. <dependency>
  2. <groupId>org.apache.solr</groupId>
  3. <artifactId>solr-solrj</artifactId>
  4. <version>${solr.version}</version>
  5. </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.

  1. public class JavaQueryTest {
  2.  
  3. private final static String QUERY_URL = "http://127.0.0.1:8080/customers/customers";
  4. private HttpSolrServer solrServer;
  5. private SolrQuery solrQuery;
  6.  
  7. @Before
  8. public void setUp() throws Exception {
  9. solrServer = new HttpSolrServer(QUERY_URL);
  10. solrServer.setAllowCompression(true);
  11. solrServer.setMaxRetries(5);
  12. solrQuery = new SolrQuery();
  13. }
  14.  
  15. @Test
  16. public void testQueryFuzzy() throws Exception {
  17. solrQuery.setQuery("TOURET~");
  18. solrQuery.addSort("dtcrea", SolrQuery.ORDER.asc);
  19. QueryResponse response = solrServer.query(solrQuery);
  20. assertNotNull(response);
  21. assertNotNull(response.getResults());
  22. assertFalse(response.getResults().isEmpty());
  23. System.out.println("Premier champ:" + response.getResults().get(1).toString());
  24. List<CustomerResource> customers = response.getBeans(CustomerResource.class);
  25. assertNotNull(customers);
  26. assertFalse(customers.isEmpty());
  27. }
  28. }
Vus : 1003
Publié par Littlewing : 368