共计 7863 个字符,预计需要花费 20 分钟才能阅读完成。
原题目:Spring 认证中国教育管理中心 -Apache Solr 的 Spring 数据教程三(Spring 中国教育管理中心)
Apache Solr 的 Spring 数据教程三
- 杂项 Solr 操作反对
本章涵盖了对无奈通过存储库接口间接拜访的 Solr 操作(例如分面)的额定反对。倡议将这些操作增加为自定义实现,如 Spring Data Repositories 的自定义实现中所述。
4.1. 汇合 / 外围名称
应用 @SolrDocument 正文,能够通过给它一个动态值或应用 SpEL 进行动静评估来自定义应用的汇合名称。
@SolrDocument(collection = “techproducts”)
class StaticCollectionName {…}
@SolrDocument(collection = “#{@someBean.getCollectionName()}”)
class DynamicCollectionName {…}
正文的类型 @SolrDocument 可通过 targetType 表达式中的变量取得。
4.2. 局部更新
PartialUpdates 能够应用 PartialUpdatewhich implements 来实现 Update。
PartialUpdate update = new PartialUpdate(“id”, “123”);
update.add(“name”, “updated-name”);
solrTemplate.saveBean(“collection-1”, update);
4.3. 投影
能够通过 @Query 应用字段值来利用投影。
@Query(fields = { “name”, “id”})
List<ProductBean> findByNameStartingWith(String name);
4.4. 刻面
应用 不能间接利用分面 SolrRepository,但 SolrTemplate 反对此性能。以下示例显示了一个方面查问:
FacetQuery query = new SimpleFacetQuery(new Criteria(Criteria.WILDCARD).expression(Criteria.WILDCARD))
.setFacetOptions(new FacetOptions().addFacetOnField(“name”).setFacetLimit(5));
FacetPage<Product> page = solrTemplate.queryForFacetPage(“collection-1”, query, Product.class);
字段或查问的方面也能够应用 @Facet. 请记住,后果是 FacetPage.
Using@Facet 容许您定义应用输出参数作为值的占位符。
以下示例应用 @Facet 正文来定义构面查问:
@Query(value = “:“)
@Facet(fields = { “name”}, limit = 5)
FacetPage<Product> findAllFacetOnName(Pageable page);
以下示例显示了另一个带有前缀的构面查问:
@Query(value = “popularity:?0”)
@Facet(fields = { “name”}, limit = 5, prefix=”?1″)
FacetPage<Product> findByPopularityFacetOnName(int popularity, String prefix, Pageable page);
Solr 容许在每个字段的根底上定义方面参数。为了向定义的字段增加非凡的方面选项,请应用 FieldWithFacetParameters,如以下示例所示:
// produces: f.name.facet.prefix=spring
FacetOptions options = new FacetOptions();
options.addFacetOnField(new FieldWithFacetParameters(“name”).setPrefix(“spring”));
4.4.1. 范畴分面
您能够通过在 上配置所需范畴来创立范畴分面查问 FacetOptions。您能够通过创立 FacetOptions 实例、将选项设置为 aFacetQuery 并通过 查问分面页面来申请范畴 SolrTemplate,如下所示。
FacetOptions facetOptions = new FacetOptions()
.addFacetByRange(
new FieldWithNumericRangeParameters("price", 5, 20, 5)
.setHardEnd(true)
.setInclude(FacetRangeInclude.ALL)
)
.addFacetByRange(
new FieldWithDateRangeParameters("release", new Date(1420070400), new Date(946684800), "+1YEAR")
.setInclude(FacetRangeInclude.ALL)
.setOther(FacetRangeOther.BEFORE)
);
facetOptions.setFacetMinCount(0);
Criteria criteria = new SimpleStringCriteria(“:“);
SimpleFacetQuery facetQuery = new SimpleFacetQuery(criteria).setFacetOptions(facetOptions);
FacetPage<ExampleSolrBean> statResultPage = solrTemplate.queryForFacetPage(“collection-1”, facetQuery, ExampleSolrBean.class);
构面范畴申请的字段有两种实现:
数字分面范畴:用于对数字字段执行范畴分面。要申请范畴分面,您能够应用 org.springframework.data.solr.core.query.FacetOptions.FieldWithNumericRangeParameters 该类的实例。它的实例化须要一个字段名、一个起始值(数字)、一个完结值(数字)和一个间隙(数字);
日期分面范畴:用于对日期字段执行范畴分面。要申请范畴分面,您能够应用 org.springframework.data.solr.core.query.FacetOptions.FieldWithDateRangeParameters 该类的实例。它的实例化须要一个字段名、一个开始值(日期)、一个完结值(日期)和一个间隙(字符串)。您能够应用 org.apache.solr.util.DateMathParser(例如,+6MONTHS+3DAYS/DAY 示意将来六个月零三天,四舍五入到最近的一天)来定义此类字段的差距。
此外,能够为具备范畴参数 (
org.springframework.data.solr.core.query.FacetOptions.FieldWithRangeParameters)的字段配置以下属性:
Hard End:setHardEnd(Boolean)定义最初一个范畴是否应该忽然完结,即便完结不满足 (start – end) % gap = 0。
包含:setInclude(org.apache.solr.common.params.FacetParams.FacetRangeInclude)定义范畴方面申请上的边界(上限和下限)应如何解决(不包含或不包含在内)。
其余:setOther(org.apache.solr.common.params.FacetParams.FacetRangeOther)定义范畴分面的附加(其余)计数(例如范畴分面开始之前、范畴分面完结之后或什至开始和完结之间的文档计数)。
4.4.2. 枢轴刻面
也反对 Pivot faceting(决策树),能够应用 @Facet 注解查问,如下:
public interface {
@Facet(pivots = @Pivot({ "category", "dimension"}, pivotMinCount = 0))
FacetPage<Product> findByTitle(String title, Pageable page);
@Facet(pivots = @Pivot({ "category", "dimension"}))
FacetPage<Product> findByDescription(String description, Pageable page);
}
或者,能够应用 查问 SolrTemplate,如下所示:
FacetQuery facetQuery = new SimpleFacetQuery(new SimpleStringCriteria(“title:foo”));
FacetOptions facetOptions = new FacetOptions();
facetOptions.setFacetMinCount(0);
facetOptions.addFacetOnPivot(“category”,”dimension”);
facetQuery.setFacetOptions(facetOptions);
FacetPage<Product> facetResult = solrTemplate.queryForFacetPage(“collection-1”, facetQuery, Product.class);
要检索数据透视后果,请应用以下 getPivot 办法:
List<FacetPivotFieldEntry> pivot = facetResult.getPivot(new SimplePivotField(“categories”,”available”));
4.5. 条款
术语向量不能间接在其中应用,SolrRepository 但能够通过 利用 SolrTemplate。请记住,后果是 TermsPage. 以下示例显示了如何创立术语查问:
TermsQuery query = SimpleTermsQuery.queryBuilder().fields(“name”).build();
TermsPage page = solrTemplate.queryForTermsPage(“collection-1”, query);
4.6. 后果分组和字段折叠
后果分组不能间接在外部应用,SolrRepository 但能够通过 利用 SolrTemplate。请记住,后果是 GroupPage. 以下示例显示了如何创立后果组:
Field field = new SimpleField(“popularity”);
Function func = ExistsFunction.exists(“description”);
Query query = new SimpleQuery(“inStock:true”);
SimpleQuery groupQuery = new SimpleQuery(new SimpleStringCriteria(“:“));
GroupOptions groupOptions = new GroupOptions()
.addGroupByField(field)
.addGroupByFunction(func)
.addGroupByQuery(query);
groupQuery.setGroupOptions(groupOptions);
GroupPage<Product> page = solrTemplate.queryForGroupPage(“collection-1”, query, Product.class);
GroupResult<Product> fieldGroup = page.getGroupResult(field);
GroupResult<Product> funcGroup = page.getGroupResult(func);
GroupResult<Product> queryGroup = page.getGroupResult(query);
4.7. 现场统计
现场统计用于检索统计(max,min,sum,count,mean,missing,stddev,和 distinct 计算)从给定的 Solr 畛域。您能够提供 StatsOptions 您的查问并 FieldStatsResult 从返回的 StatsPage. 例如,您能够应用 SolrTemplate,如下所示:
// simple field stats
StatsOptions statsOptions = new StatsOptions().addField(“price”);
// query
SimpleQuery statsQuery = new SimpleQuery(“:“);
statsQuery.setStatsOptions(statsOptions);
StatsPage<Product> statsPage = solrTemplate.queryForStatsPage(“collection-1”, statsQuery, Product.class);
// retrieving stats info
FieldStatsResult priceStatResult = statResultPage.getFieldStatsResult(“price”);
Object max = priceStatResult.getMax();
Long missing = priceStatResult.getMissing();
您能够通过应用 正文存储库办法来取得雷同的后果 @Stats,如下所示:
@Query(“name:?0”)
@Stats(value = { “price”})
StatsPage<Product> findByName(String name, Pageable page);
还反对不同的计算和分面:
// for distinct calculation
StatsOptions statsOptions = new StatsOptions()
.addField("category")
// for distinct calculation
.setCalcDistinct(true)
// for faceting
.addFacet("availability");
// query
SimpleQuery statsQuery = new SimpleQuery(“:“);
statsQuery.setStatsOptions(statsOptions);
StatsPage<Product> statsPage = solrTemplate.queryForStatsPage(“collection-1”, statsQuery, Product.class);
// field stats
FieldStatsResult categoryStatResult = statResultPage.getFieldStatsResult(“category”);
// retrieving distinct
List<Object> categoryValues = priceStatResult.getDistinctValues();
Long distinctCount = categoryStatResult.getDistinctCount();
// retrieving faceting
Map<String, StatsResult> availabilityFacetResult = categoryStatResult.getFacetStatsResult(“availability”);
Long availableCount = availabilityFacetResult.get(“true”).getCount();
后面示例的正文(因而更短)版本如下:
@Query(“name:?0”)
@Stats(value = “category”, facets = { “availability”}, calcDistinct = true)
StatsPage<Product> findByName(String name);
为了执行选择性分面或选择性不同计算,您能够应用 @SelectiveStats,如下所示:
// selective distinct faceting
…
Field facetField = getFacetField();
StatsOptions statsOptions = new StatsOptions()
.addField("price")
.addField("category").addSelectiveFacet("name").addSelectiveFacet(facetField);
…
// or annotating repository method as follows
…
@Stats(value = “price”, selective = @SelectiveStats(field = “category”, facets = { “name”, “available”}))
…
// selective distinct calculation
…
StatsOptions statsOptions = new StatsOptions()
.addField("price")
.addField("category").setSelectiveCalcDistinct(true);
…
// or annotating repository method as follows
…
@Stats(value = “price”, selective = @SelectiveStats(field = “category”, calcDistinct = true))
…
4.8. 过滤查问
过滤查问进步了查问速度并且不影响文档分数。咱们倡议将天文空间搜寻作为过滤查问来实现。
在 Solr 中,除非另有阐明,所有间隔单位都是公里,点的单位是纬度和经度。
以下示例显示了天文点(在本例中为奥地利)的过滤器查问:
Query query = new SimpleQuery(new Criteria(“category”).is(“supercalifragilisticexpialidocious”));
FilterQuery fq = new SimpleFilterQuery(new Criteria(“store”)
.near(new Point(48.305478, 14.286699), new Distance(5)));
query.addFilterQuery(fq);
您还能够应用 定义简略的过滤器查问 @Query。
Using@Query 容许您定义应用输出参数作为值的占位符。
以下示例显示了带有占位符 (:)的查问:
@Query(value = “:“, filters = {“inStock:true”, “popularity:[* TO 3]” })
List<Product> findAllFilterAvailableTrueAndPopularityLessThanEqual3();