BAEL-347-Full-text search with SOLR (#1254)
* solr-fulltext-search module created * solr-fulltext-search modue created * solr-fulltext-search change s * pom changes merged from upstream
This commit is contained in:
parent
1bfc944c5a
commit
442c00545c
|
@ -18,7 +18,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-solrj</artifactId>
|
||||
<version>6.1.0</version>
|
||||
<version>6.4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package com.baeldung.solr.fulltext.search.model;
|
||||
|
||||
import org.apache.solr.client.solrj.beans.Field;
|
||||
|
||||
public class Item {
|
||||
|
||||
@Field
|
||||
private String id;
|
||||
|
||||
@Field
|
||||
private String description;
|
||||
|
||||
@Field
|
||||
private String category;
|
||||
|
||||
@Field
|
||||
private float price;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public float getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(float price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.solr.fulltext.search.service;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
|
||||
import com.baeldung.solr.fulltext.search.model.Item;
|
||||
|
||||
public interface ItemSearchService {
|
||||
|
||||
public void index(String id, String description, String category, float price) throws SolrServerException, IOException;
|
||||
|
||||
public void indexBean(Item item) throws IOException, SolrServerException;
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.solr.fulltext.search.service;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
|
||||
import com.baeldung.solr.fulltext.search.model.Item;
|
||||
|
||||
public class ItemSearchServiceImpl implements ItemSearchService {
|
||||
|
||||
private final SolrClient solrClient;
|
||||
|
||||
public ItemSearchServiceImpl(SolrClient solrClient) {
|
||||
this.solrClient = solrClient;
|
||||
}
|
||||
|
||||
public void index(String id, String description, String category, float price) throws SolrServerException, IOException {
|
||||
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();
|
||||
}
|
||||
|
||||
public void indexBean(Item item) throws IOException, SolrServerException {
|
||||
solrClient.addBean(item);
|
||||
solrClient.commit();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,374 @@
|
|||
package com.baeldung.solr.fulltext.search.service;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.client.solrj.impl.HttpSolrClient;
|
||||
import org.apache.solr.client.solrj.response.FacetField.Count;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
import org.apache.solr.client.solrj.response.RangeFacet;
|
||||
import org.apache.solr.client.solrj.response.SpellCheckResponse;
|
||||
import org.apache.solr.client.solrj.response.SpellCheckResponse.Suggestion;
|
||||
import org.apache.solr.client.solrj.response.SuggesterResponse;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.solr.fulltext.search.model.Item;
|
||||
|
||||
public class ItemSearchServiceIntegrationTest {
|
||||
|
||||
private static SolrClient solrClient;
|
||||
private static ItemSearchService itemSearchService;
|
||||
private static final String solrUrl = "http://localhost:8987/solr/item";
|
||||
|
||||
@BeforeClass
|
||||
public static void initBeans() throws Exception {
|
||||
solrClient = new HttpSolrClient.Builder(solrUrl).build();
|
||||
itemSearchService = new ItemSearchServiceImpl(solrClient);
|
||||
|
||||
solrClient.commit();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void clearSolrData() throws Exception {
|
||||
solrClient.deleteByQuery("*:*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenIndexing_thenAvailableOnRetrieval() throws Exception {
|
||||
itemSearchService.index("hm0001", "Washing Machine", "Home Appliances", 450f);
|
||||
final SolrDocument indexedDoc = solrClient.getById("hm0001");
|
||||
assertEquals("hm0001", indexedDoc.get("id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenIndexingBean_thenAvailableOnRetrieval() throws Exception {
|
||||
Item item = new Item();
|
||||
item.setId("hm0002");
|
||||
item.setCategory("Televisions");
|
||||
item.setDescription("LED TV 32");
|
||||
item.setPrice(500);
|
||||
itemSearchService.indexBean(item);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingByBasicQuery_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "LED TV 32", "Brand1 Home Appliances", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("brand1");
|
||||
query.setStart(0);
|
||||
query.setRows(10);
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(3, items.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithWildCard_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "LED TV 32", "Brand1 Home Appliances", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*rand?");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(3, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithLogicalOperators_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "Brand2 LED TV 32", "Washing Appliances", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("brand1 AND (Washing OR Refrigerator)");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFields_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("0003", "Brand2 LED TV 32", "Brand1 Washing Home Appliances", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("description:Brand* AND category:*Washing*");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(1, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithPhrase_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("washing MachIne");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithRealPhrase_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("\"washing machine\"");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(1, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingPhraseWithProximity_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("\"Washing equipment\"~2");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(1, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithPriceRange_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Home Appliances", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("price:[100 TO 300]");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(3, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithPriceRangeInclusiveExclusive_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Home Appliances", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("price:{100 TO 300]");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFilterQuery_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
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 tools and equipment ", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("price:[100 TO 300]");
|
||||
query.addFilterQuery("description:Brand1", "category:Home Appliances");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFacetFields_thenAllMatchingFacetsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*:*");
|
||||
query.addFacetField("category");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Count> facetResults = response.getFacetField("category").getValues();
|
||||
|
||||
assertEquals(2, facetResults.size());
|
||||
|
||||
for (Count count : facetResults) {
|
||||
if ("categorya".equalsIgnoreCase(count.getName())) {
|
||||
assertEquals(2, count.getCount());
|
||||
} else if ("categoryb".equalsIgnoreCase(count.getName())) {
|
||||
assertEquals(2, count.getCount());
|
||||
} else {
|
||||
fail("unexpected category");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFacetQuery_thenAllMatchingFacetsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*:*");
|
||||
|
||||
query.addFacetQuery("Washing OR Refrigerator");
|
||||
query.addFacetQuery("Brand2");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
Map<String, Integer> facetQueryMap = response.getFacetQuery();
|
||||
|
||||
assertEquals(2, facetQueryMap.size());
|
||||
|
||||
for (Map.Entry<String, Integer> entry : facetQueryMap.entrySet()) {
|
||||
String facetQuery = entry.getKey();
|
||||
|
||||
if ("Washing OR Refrigerator".equals(facetQuery)) {
|
||||
assertEquals(Integer.valueOf(2), entry.getValue());
|
||||
} else if ("Brand2".equals(facetQuery)) {
|
||||
assertEquals(Integer.valueOf(2), entry.getValue());
|
||||
} else {
|
||||
fail("unexpected query");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFacetRange_thenAllMatchingFacetsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 125f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 150f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*:*");
|
||||
|
||||
query.addNumericRangeFacet("price", 100, 275, 25);
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<RangeFacet> rangeFacets = response.getFacetRanges().get(0).getCounts();
|
||||
|
||||
assertEquals(7, rangeFacets.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithHitHighlighting_thenKeywordsShouldBeHighlighted() throws Exception {
|
||||
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");
|
||||
query.setHighlightSimplePre("<strong>");
|
||||
query.setHighlightSimplePost("</strong>");
|
||||
QueryResponse response = solrClient.query(query);
|
||||
|
||||
Map<String, Map<String, List<String>>> hitHighlightedMap = response.getHighlighting();
|
||||
Map<String, List<String>> highlightedFieldMap = hitHighlightedMap.get("hm0001");
|
||||
List<String> highlightedList = highlightedFieldMap.get("category");
|
||||
String highLightedText = highlightedList.get(0);
|
||||
|
||||
assertEquals("Home <strong>Appliances</strong>", highLightedText);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithKeywordWithMistake_thenSpellingSuggestionsShouldBeReturned() throws Exception {
|
||||
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("hme");
|
||||
query.set("spellcheck", "on");
|
||||
QueryResponse response = solrClient.query(query);
|
||||
|
||||
SpellCheckResponse spellCheckResponse = response.getSpellCheckResponse();
|
||||
|
||||
assertEquals(false, spellCheckResponse.isCorrectlySpelled());
|
||||
|
||||
Suggestion suggestion = spellCheckResponse.getSuggestions().get(0);
|
||||
|
||||
assertEquals("hme", suggestion.getToken());
|
||||
|
||||
List<String> alternatives = suggestion.getAlternatives();
|
||||
String alternative = alternatives.get(0);
|
||||
|
||||
assertEquals("home", alternative);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithIncompleteKeyword_thenKeywordSuggestionsShouldBeReturned() throws Exception {
|
||||
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", "Home washing equipments", 250f);
|
||||
|
||||
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<String, List<String>> suggestedTerms = suggesterResponse.getSuggestedTerms();
|
||||
List<String> suggestions = suggestedTerms.get("mySuggester");
|
||||
|
||||
assertEquals(2, suggestions.size());
|
||||
|
||||
for (String term : suggestions) {
|
||||
if (!"Home Appliances".equals(term) && !"Home washing equipments".equals(term)) {
|
||||
fail("Unexpected suggestions");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue