Ricerca full-text con Solr

1. Panoramica

In questo articolo, esploreremo un concetto fondamentale nel motore di ricerca Apache Solr: la ricerca full-text.

Apache Solr è un framework open source, progettato per gestire milioni di documenti. Esamineremo le funzionalità principali di esso con esempi utilizzando la libreria Java - SolrJ.

2. Configurazione Maven

Dato che Solr è open source, possiamo semplicemente scaricare il file binario e avviare il server separatamente dalla nostra applicazione.

Per comunicare con il server, definiremo la dipendenza Maven per il client SolrJ:

 org.apache.solr solr-solrj 6.4.2 

Puoi trovare l'ultima dipendenza qui.

3. Indicizzazione dei dati

Per indicizzare e cercare i dati, dobbiamo creare un nucleo ; creeremo un elemento con nome per indicizzare i nostri dati.

Prima di farlo, abbiamo bisogno che i dati vengano indicizzati sul server, in modo che diventino ricercabili.

Esistono molti modi diversi per indicizzare i dati. Possiamo utilizzare gestori di importazione dati per importare dati direttamente da database relazionali, caricare dati con Solr Cell utilizzando Apache Tika o caricare dati XML / XSLT, JSON e CSV utilizzando gestori di indice.

3.1. Indicizzazione documento Solr

Possiamo indicizzare i dati in un core creando SolrInputDocument . Innanzitutto, dobbiamo popolare il documento con i nostri dati e quindi chiamare solo l'API di SolrJ per indicizzare il documento:

SolrInputDocument doc = new SolrInputDocument(); doc.addField("id", id); doc.addField("description", description); doc.addField("category", category); doc.addField("price", price); solrClient.add(doc); solrClient.commit();

Nota che l' ID dovrebbe essere naturalmente univoco per articoli diversi . Avere un ID di un documento già indicizzato aggiornerà quel documento.

3.2. Indicizzazione dei fagioli

SolrJ fornisce API per l'indicizzazione dei bean Java. Per indicizzare un bean, dobbiamo annotarlo con le annotazioni @Field :

public class Item { @Field private String id; @Field private String description; @Field private String category; @Field private float price; }

Una volta ottenuto il bean, l'indicizzazione è semplice:

solrClient.addBean(item); solrClient.commit();

4. Solr Queries

La ricerca è la capacità più potente di Solr. Una volta che i documenti sono stati indicizzati nel nostro repository, possiamo cercare parole chiave, frasi, intervalli di date, ecc. I risultati vengono ordinati per rilevanza (punteggio).

4.1. Query di base

Il server espone un'API per le operazioni di ricerca. Possiamo chiamare / selezionare o / interrogare i gestori delle richieste.

Facciamo una semplice ricerca:

SolrQuery query = new SolrQuery(); query.setQuery("brand1"); query.setStart(0); query.setRows(10); QueryResponse response = solrClient.query(query); List items = response.getBeans(Item.class);

SolrJ utilizzerà internamente il parametro di query principale q nella sua richiesta al server. Il numero di record restituiti sarà 10, indicizzato da zero quando l' inizio e le righe non sono specificati.

La query di ricerca sopra cercherà tutti i documenti che contengono la parola completa "marca1" in uno dei suoi campi indicizzati. Tieni presente che le ricerche semplici non fanno distinzione tra maiuscole e minuscole.

Diamo un'occhiata a un altro esempio. Vogliamo cercare qualsiasi parola contenente "rand" , che inizi con un numero qualsiasi di caratteri e termini con un solo carattere. Possiamo usare caratteri jolly * e ? nella nostra domanda:

query.setQuery("*rand?");

Le query Solr supportano anche operatori booleani come in SQL:

query.setQuery("brand1 AND (Washing OR Refrigerator)");

Tutti gli operatori booleani devono essere tutti in maiuscolo; quelli supportati dal parser di query sono AND , OR, NOT , + e -.

Inoltre, se vogliamo cercare su campi specifici invece che su tutti i campi indicizzati, possiamo specificarli nella query:

query.setQuery("description:Brand* AND category:*Washing*");

4.2. Query a frase

Fino a questo punto, il nostro codice ha cercato le parole chiave nei campi indicizzati. Possiamo anche fare ricerche di frasi sui campi indicizzati:

query.setQuery("Washing Machine");

Quando abbiamo una frase come " Washing Machine ", il parser di query standard di Solr la analizza in " Washing OR Machine ". Per cercare un'intera frase, possiamo solo aggiungere l'espressione tra virgolette doppie:

query.setQuery("\"Washing Machine\"");

Possiamo usare la ricerca per prossimità per trovare parole entro distanze specifiche . Se vogliamo trovare le parole distanti almeno due parole, possiamo utilizzare la seguente query:

query.setQuery("\"Washing equipment\"~2");

4.3. Intervallo di query

Le query di intervallo consentono di ottenere documenti i cui campi sono compresi tra intervalli specifici.

Supponiamo di voler trovare articoli il cui prezzo oscilla tra 100 e 300:

query.setQuery("price:[100 TO 300]");

La query precedente troverà tutti gli elementi il ​​cui prezzo è compreso tra 100 e 300 inclusi. Possiamo usare " } " e " { " per escludere i punti finali:

query.setQuery("price:{100 TO 300]");

4.4. Filtra query

Le query di filtro possono essere utilizzate per limitare il superset di risultati che possono essere restituiti. La query del filtro non influenza il punteggio:

SolrQuery query = new SolrQuery(); query.setQuery("price:[100 TO 300]"); query.addFilterQuery("description:Brand1","category:Home Appliances");

In genere, la query di filtro conterrà query di uso comune. Poiché sono spesso riutilizzabili, vengono memorizzati nella cache per rendere la ricerca più efficiente.

5. Ricerca sfaccettata

Faceting helps to arrange search results into group counts. We can facet fields, query or ranges.

5.1. Field Faceting

For example, we want to get the aggregated counts of categories in the search result. We can add category field in our query:

query.addFacetField("category"); QueryResponse response = solrClient.query(query); List facetResults = response.getFacetField("category").getValues();

The facetResults will contain counts of each category in the results.

5.2. Query Faceting

Query faceting is very useful when we want to bring back counts of subqueries:

query.addFacetQuery("Washing OR Refrigerator"); query.addFacetQuery("Brand2"); QueryResponse response = solrClient.query(query); Map facetQueryMap = response.getFacetQuery();

As a result, the facetQueryMap will have counts of facet queries.

5.3. Range Faceting

Range faceting is used to get the range counts in the search results. The following query will return the counts of price ranges between 100 and 251, gapped by 25:

query.addNumericRangeFacet("price", 100, 275, 25); QueryResponse response = solrClient.query(query); List rangeFacets = response.getFacetRanges().get(0).getCounts();

Apart from numeric ranges, Solr also supports date ranges, interval faceting, and pivot faceting.

6. Hit Highlighting

We may want the keywords in our search query to be highlighted in the results. This will be very helpful to get a better picture of the results. Let's index some documents and define keywords to be highlighted:

itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f); itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f); itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f); itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing equipments", 250f); SolrQuery query = new SolrQuery(); query.setQuery("Appliances"); query.setHighlight(true); query.addHighlightField("category"); QueryResponse response = solrClient.query(query); Map
    
     > hitHighlightedMap = response.getHighlighting(); Map
     
       highlightedFieldMap = hitHighlightedMap.get("hm0001"); List highlightedList = highlightedFieldMap.get("category"); String highLightedText = highlightedList.get(0);
     
    

We'll get the highLightedText as “Home Appliances. Please notice that the search keyword Appliances is tagged with . Default highlighting tag used by Solr is , but we can change this by setting the pre and post tags:

query.setHighlightSimplePre(""); query.setHighlightSimplePost("");

7. Search Suggestions

One of the important features that Solr supports are suggestions. If the keywords in the query contain spelling mistakes or if we want to suggest to autocomplete a search keyword, we can use the suggestion feature.

7.1. Spell Checking

The standard search handler does not include spell checking component; it has to be configured manually. There are three ways to do it. You can find the configuration details in the official wiki page. In our example, we'll use IndexBasedSpellChecker, which uses indexed data for keyword spell checking.

Let's search for a keyword with spelling mistake:

query.setQuery("hme"); query.set("spellcheck", "on"); QueryResponse response = solrClient.query(query); SpellCheckResponse spellCheckResponse = response.getSpellCheckResponse(); Suggestion suggestion = spellCheckResponse.getSuggestions().get(0); List alternatives = suggestion.getAlternatives(); String alternative = alternatives.get(0);

Expected alternative for our keyword “hme” should be “home” as our index contains the term “home”. Note that spellcheck has to be activated before executing the search.

7.2. Auto Suggesting Terms

We may want to get the suggestions of incomplete keywords to assist with the search. Solr's suggest component has to be configured manually. You can find the configuration details in its official wiki page.

We have configured a request handler named /suggest to handle suggestions. Let's get suggestions for keyword “Hom”:

SolrQuery query = new SolrQuery(); query.setRequestHandler("/suggest"); query.set("suggest", "true"); query.set("suggest.build", "true"); query.set("suggest.dictionary", "mySuggester"); query.set("suggest.q", "Hom"); QueryResponse response = solrClient.query(query); SuggesterResponse suggesterResponse = response.getSuggesterResponse(); Map
      
        suggestedTerms = suggesterResponse.getSuggestedTerms(); List suggestions = suggestedTerms.get("mySuggester");
      

The list suggestions should contain all words and phrases. Note that we have configured a suggester named mySuggester in our configuration.

8. Conclusion

This article is a quick intro to the search engine's capabilities and features of Solr.

We touched on many features, but these are of course just scratching the surface of what we can do with an advanced and mature search server such as Solr.

The examples used here are available as always, over on GitHub.