Spring认证中国教育管理中心-Apache Solr 的 Spring 数据教程三

原标题:Spring认证中国教育管理中心-Apache Solr 的 Spring 数据教程三(Spring中国教育管理中心)

Apache Solr 的 Spring 数据教程三

  1. 杂项 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 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 page = solrTemplate.queryForFacetPage("collection-1", query, Product.class);
字段或查询的方面也可以使用@Facet. 请记住,结果是FacetPage.

Using@Facet允许您定义使用输入参数作为值的占位符。

以下示例使用@Facet注释来定义构面查询:

@Query(value = ":")
@Facet(fields = { "name" }, limit = 5)
FacetPage findAllFacetOnName(Pageable page);
以下示例显示了另一个带有前缀的构面查询:

@Query(value = "popularity:?0")
@Facet(fields = { "name" }, limit = 5, prefix="?1")
FacetPage 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 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 findByTitle(String title, Pageable page);

@Facet(pivots = @Pivot({ "category", "dimension" }))
FacetPage 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 facetResult = solrTemplate.queryForFacetPage("collection-1", facetQuery, Product.class);
要检索数据透视结果,请使用以下getPivot方法:

List 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 page = solrTemplate.queryForGroupPage("collection-1", query, Product.class);

GroupResult fieldGroup = page.getGroupResult(field);
GroupResult funcGroup = page.getGroupResult(func);
GroupResult 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 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 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 statsPage = solrTemplate.queryForStatsPage("collection-1", statsQuery, Product.class);

// field stats
FieldStatsResult categoryStatResult = statResultPage.getFieldStatsResult("category");

// retrieving distinct
List categoryValues = priceStatResult.getDistinctValues();
Long distinctCount = categoryStatResult.getDistinctCount();

// retrieving faceting
Map availabilityFacetResult = categoryStatResult.getFacetStatsResult("availability");
Long availableCount = availabilityFacetResult.get("true").getCount();
前面示例的注释(因此更短)版本如下:

@Query("name:?0")
@Stats(value = "category", facets = { "availability" }, calcDistinct = true)
StatsPage 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 findAllFilterAvailableTrueAndPopularityLessThanEqual3();