basic mechanism for term facets

This commit is contained in:
akonczak
2013-05-20 09:47:26 +01:00
parent b421cb5044
commit b2572d4950
29 changed files with 1633 additions and 512 deletions

View File

@@ -0,0 +1,66 @@
package org.springframework.data.elasticsearch;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import java.util.ArrayList;
import java.util.List;
/**
* Simple type to test facets
*/
@Document(indexName = "articles", type = "article", shards = 1, replicas = 0, refreshInterval = "-1")
public class Article {
@Id
private String id;
private String title;
@Field(type = "string", facetable = true)
private List<String> authors = new ArrayList<String>();
@Field(type = "integer", facetable = true)
private List<Integer> publishedYears = new ArrayList<Integer>();
public Article() {
}
public Article(String id) {
this.id = id;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<String> getAuthors() {
return authors;
}
public void setAuthors(List<String> authors) {
this.authors = authors;
}
public List<Integer> getPublishedYears() {
return publishedYears;
}
public void setPublishedYears(List<Integer> publishedYears) {
this.publishedYears = publishedYears;
}
}

View File

@@ -0,0 +1,46 @@
package org.springframework.data.elasticsearch;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import java.util.ArrayList;
/**
* Simple type to test facets
*/
public class ArticleBuilder {
private Article resutl;
public ArticleBuilder(String id) {
resutl = new Article(id);
}
public ArticleBuilder title(String title) {
resutl.setTitle(title);
return this;
}
public ArticleBuilder addAuthor(String author) {
resutl.getAuthors().add(author);
return this;
}
public ArticleBuilder addPublishedYear(Integer year) {
resutl.getPublishedYears().add(year);
return this;
}
public Article build() {
return resutl;
}
public IndexQuery buildIndex(){
IndexQuery indexQuery = new IndexQuery();
indexQuery.setId(resutl.getId());
indexQuery.setObject(resutl);
return indexQuery;
}
}

View File

@@ -0,0 +1,350 @@
/*
* Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.search.facet.FacetBuilders;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.Article;
import org.springframework.data.elasticsearch.ArticleBuilder;
import org.springframework.data.elasticsearch.core.facet.Term;
import org.springframework.data.elasticsearch.core.facet.TermResult;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.elasticsearch.index.query.FilterBuilders.termFilter;
import static org.elasticsearch.index.query.QueryBuilders.fieldQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Jonathan Yan
* @author Artur Konczak
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
public class ElasticsearchTemplateFacetTests {
public static final String RIZWAN_IDREES = "Rizwan Idrees";
public static final String MOHSIN_HUSEN = "Mohsin Husen";
public static final String JONATHAN_YAN = "Jonathan Yan";
public static final String ARTUR_KONCZAK = "Artur Konczak";
public static final int YEAR_2002 = 2002;
public static final int YEAR_2001 = 2001;
public static final int YEAR_2000 = 2000;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Before
public void before() {
elasticsearchTemplate.deleteIndex(Article.class);
elasticsearchTemplate.createIndex(Article.class);
elasticsearchTemplate.putMapping(Article.class);
elasticsearchTemplate.refresh(Article.class, true);
IndexQuery article1 = new ArticleBuilder("1").title("article four").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addAuthor(JONATHAN_YAN).buildIndex();
IndexQuery article2 = new ArticleBuilder("2").title("article three").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addPublishedYear(YEAR_2000).buildIndex();
IndexQuery article3 = new ArticleBuilder("3").title("article two").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).buildIndex();
IndexQuery article4 = new ArticleBuilder("4").title("article one").addAuthor(RIZWAN_IDREES).addPublishedYear(YEAR_2002).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).buildIndex();
elasticsearchTemplate.index(article1);
elasticsearchTemplate.index(article2);
elasticsearchTemplate.index(article3);
elasticsearchTemplate.index(article4);
elasticsearchTemplate.refresh(Article.class, true);
}
@Test
public void shouldReturnFacetedAuthorsForGivenQueryWithDefaultOrder() {
// given
String facetName = "fauthors";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withFacet(new TermFacetRequestBuilder(facetName).withStringFields("authors").build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
TermResult facet = (TermResult) result.getFacet(facetName);
Term term = facet.getTerms().get(0);
assertThat(term.getTerm(), is(RIZWAN_IDREES));
assertThat(term.getCount(), is(4));
term = facet.getTerms().get(1);
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
assertThat(term.getCount(), is(3));
term = facet.getTerms().get(2);
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
assertThat(term.getCount(), is(2));
term = facet.getTerms().get(3);
assertThat(term.getTerm(), is(JONATHAN_YAN));
assertThat(term.getCount(), is(1));
}
@Test
public void shouldReturnFacetedAuthorsForGivenFilteredQuery() {
// given
String facetName = "fauthors";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title","four")))
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().withStringFields("authors").build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(3)));
TermResult facet = (TermResult) result.getFacet(facetName);
Term term = facet.getTerms().get(0);
assertThat(term.getTerm(), is(RIZWAN_IDREES));
assertThat(term.getCount(), is(3));
term = facet.getTerms().get(1);
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
assertThat(term.getCount(), is(2));
term = facet.getTerms().get(2);
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
assertThat(term.getCount(), is(1));
}
@Test
public void shouldReturnFacetedAuthorsForGivenQueryOrderedByTerm() {
// given
String facetName = "fauthors";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new TermFacetRequestBuilder(facetName).withStringFields("authors").ascTerm().build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
TermResult facet = (TermResult) result.getFacet(facetName);
Term term = facet.getTerms().get(0);
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
assertThat(term.getCount(), is(3));
term = facet.getTerms().get(1);
assertThat(term.getTerm(), is(JONATHAN_YAN));
assertThat(term.getCount(), is(1));
term = facet.getTerms().get(2);
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
assertThat(term.getCount(), is(2));
term = facet.getTerms().get(3);
assertThat(term.getTerm(), is(RIZWAN_IDREES));
assertThat(term.getCount(), is(4));
}
@Test
public void shouldReturnFacetedAuthorsForGivenQueryOrderedByCountAsc() {
// given
String facetName = "fauthors";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new TermFacetRequestBuilder(facetName).withStringFields("authors").ascCount().build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
TermResult facet = (TermResult) result.getFacet(facetName);
Term term = facet.getTerms().get(0);
assertThat(term.getTerm(), is(JONATHAN_YAN));
assertThat(term.getCount(), is(1));
term = facet.getTerms().get(1);
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
assertThat(term.getCount(), is(2));
term = facet.getTerms().get(2);
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
assertThat(term.getCount(), is(3));
term = facet.getTerms().get(3);
assertThat(term.getTerm(), is(RIZWAN_IDREES));
assertThat(term.getCount(), is(4));
}
@Test
public void shouldReturnFacetedYearsForGivenQuery() {
// given
String facetName = "fyears";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new TermFacetRequestBuilder(facetName).withNumberFields("publishedYears").descCount().build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
TermResult facet = (TermResult) result.getFacet(facetName);
assertThat(facet.getTerms().size(), is(equalTo(3)));
Term term = facet.getTerms().get(0);
assertThat(term.getTerm(), is(Integer.toString(YEAR_2000)));
assertThat(term.getCount(), is(3));
term = facet.getTerms().get(1);
assertThat(term.getTerm(), is(Integer.toString(YEAR_2001)));
assertThat(term.getCount(), is(2));
term = facet.getTerms().get(2);
assertThat(term.getTerm(), is(Integer.toString(YEAR_2002)));
assertThat(term.getCount(), is(1));
}
@Test
public void shouldReturnSingleFacetOverYearsAndAuthorsForGivenQuery() {
// given
String facetName = "fyears";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new TermFacetRequestBuilder(facetName).withNumberFields("publishedYears").withStringFields("authors").ascTerm().build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
TermResult facet = (TermResult) result.getFacet(facetName);
assertThat(facet.getTerms().size(), is(equalTo(7)));
Term term = facet.getTerms().get(0);
assertThat(term.getTerm(), is(Integer.toString(YEAR_2000)));
assertThat(term.getCount(), is(3));
term = facet.getTerms().get(1);
assertThat(term.getTerm(), is(Integer.toString(YEAR_2001)));
assertThat(term.getCount(), is(2));
term = facet.getTerms().get(2);
assertThat(term.getTerm(), is(Integer.toString(YEAR_2002)));
assertThat(term.getCount(), is(1));
term = facet.getTerms().get(3);
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
assertThat(term.getCount(), is(3));
term = facet.getTerms().get(4);
assertThat(term.getTerm(), is(JONATHAN_YAN));
assertThat(term.getCount(), is(1));
term = facet.getTerms().get(5);
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
assertThat(term.getCount(), is(2));
term = facet.getTerms().get(6);
assertThat(term.getTerm(), is(RIZWAN_IDREES));
assertThat(term.getCount(), is(4));
}
@Test
public void shouldReturnFacetedYearsAndFacetedAuthorsForGivenQuery() {
// given
String numberFacetName = "fAuthors";
String stringFacetName = "fyears";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new TermFacetRequestBuilder(numberFacetName).withNumberFields("publishedYears").ascTerm().build())
.withFacet(new TermFacetRequestBuilder(stringFacetName).withStringFields("authors").ascTerm().build())
.build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
TermResult numberFacet = (TermResult) result.getFacet(numberFacetName);
assertThat(numberFacet.getTerms().size(), is(equalTo(3)));
Term numberTerm = numberFacet.getTerms().get(0);
assertThat(numberTerm.getTerm(), is(Integer.toString(YEAR_2000)));
assertThat(numberTerm.getCount(), is(3));
numberTerm = numberFacet.getTerms().get(1);
assertThat(numberTerm.getTerm(), is(Integer.toString(YEAR_2001)));
assertThat(numberTerm.getCount(), is(2));
numberTerm = numberFacet.getTerms().get(2);
assertThat(numberTerm.getTerm(), is(Integer.toString(YEAR_2002)));
assertThat(numberTerm.getCount(), is(1));
TermResult stringFacet = (TermResult) result.getFacet(stringFacetName);
Term stringTerm = stringFacet.getTerms().get(0);
assertThat(stringTerm.getTerm(), is(ARTUR_KONCZAK));
assertThat(stringTerm.getCount(), is(3));
stringTerm = stringFacet.getTerms().get(1);
assertThat(stringTerm.getTerm(), is(JONATHAN_YAN));
assertThat(stringTerm.getCount(), is(1));
stringTerm = stringFacet.getTerms().get(2);
assertThat(stringTerm.getTerm(), is(MOHSIN_HUSEN));
assertThat(stringTerm.getCount(), is(2));
stringTerm = stringFacet.getTerms().get(3);
assertThat(stringTerm.getTerm(), is(RIZWAN_IDREES));
assertThat(stringTerm.getCount(), is(4));
}
@Test
public void shouldReturnFacetedYearsForNativeFacet() {
// given
String facetName = "fyears";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new NativeFacetRequest(FacetBuilders.termsFacet(facetName).field("publishedYears"))).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
TermResult facet = (TermResult) result.getFacet(facetName);
assertThat(facet.getTerms().size(), is(equalTo(3)));
Term term = facet.getTerms().get(0);
assertThat(term.getTerm(), is(Integer.toString(YEAR_2000)));
assertThat(term.getCount(), is(3));
term = facet.getTerms().get(1);
assertThat(term.getTerm(), is(Integer.toString(YEAR_2001)));
assertThat(term.getCount(), is(2));
term = facet.getTerms().get(2);
assertThat(term.getTerm(), is(Integer.toString(YEAR_2002)));
assertThat(term.getCount(), is(1));
}
}

View File

@@ -465,12 +465,12 @@ public class ElasticsearchTemplateTests {
// when
Page<String> page = elasticsearchTemplate.queryForPage(searchQuery, new ResultsMapper<String>() {
@Override
public Page<String> mapResults(SearchResponse response) {
public FacetedPage<String> mapResults(SearchResponse response) {
List<String> values = new ArrayList<String>();
for (SearchHit searchHit : response.getHits()) {
values.add((String) searchHit.field("message").value());
}
return new PageImpl<String>(values);
return new FacetedPageImpl<String>(values);
}
});
// then
@@ -543,7 +543,7 @@ public class ElasticsearchTemplateTests {
while (hasRecords) {
Page<SampleEntity> page = elasticsearchTemplate.scroll(scrollId, 5000L, new ResultsMapper<SampleEntity>() {
@Override
public Page<SampleEntity> mapResults(SearchResponse response) {
public FacetedPage<SampleEntity> mapResults(SearchResponse response) {
List<SampleEntity> chunk = new ArrayList<SampleEntity>();
for (SearchHit searchHit : response.getHits()) {
if (response.getHits().getHits().length <= 0) {
@@ -556,7 +556,7 @@ public class ElasticsearchTemplateTests {
}
if(chunk.size() > 0){
return new PageImpl<SampleEntity>(chunk);
return new FacetedPageImpl<SampleEntity>(chunk);
}
return null;
}