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

2022-01-06 15:10:01 浏览数 (1)

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

4. 杂项 Solr 操作支持

本章涵盖了对无法通过存储库接口直接访问的 Solr 操作(例如分面)的额外支持。建议将这些操作添加为自定义实现,如Spring Data Repositories 的自定义实现中所述。

4.1.集合/核心名称

使用@SolrDocument注释,可以通过给它一个静态值或使用SpEL 进行动态评估来自定义使用的集合名称。

代码语言:javascript复制
@SolrDocument(collection = "techproducts")
class StaticCollectionName { ... }

@SolrDocument(collection = "#{@someBean.getCollectionName()}")
class DynamicCollectionName { ... }

注释的类型@SolrDocument可通过targetType表达式中的变量获得。

4.2.部分更新

PartialUpdates 可以使用PartialUpdatewhich implements来完成Update。

代码语言:javascript复制
PartialUpdate update = new PartialUpdate("id", "123");
update.add("name", "updated-name");
solrTemplate.saveBean("collection-1", update);

4.3.投影

可以通过@Query使用字段值来应用投影。

代码语言:javascript复制
@Query(fields = { "name", "id" })
List<ProductBean> findByNameStartingWith(String name);

4.4.刻面

使用 不能直接应用分面SolrRepository,但SolrTemplate支持此功能。以下示例显示了一个方面查询:

代码语言:javascript复制
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注释来定义构面查询:

代码语言:javascript复制
@Query(value = "*:*")
@Facet(fields = { "name" }, limit = 5)
FacetPage<Product> findAllFacetOnName(Pageable page);

以下示例显示了另一个带有前缀的构面查询:

代码语言:javascript复制
@Query(value = "popularity:?0")
@Facet(fields = { "name" }, limit = 5, prefix="?1")
FacetPage<Product> findByPopularityFacetOnName(int popularity, String prefix, Pageable page);

Solr 允许在每个字段的基础上定义方面参数。为了向定义的字段添加特殊的方面选项,请使用FieldWithFacetParameters,如以下示例所示:

代码语言:javascript复制
// produces: f.name.facet.prefix=spring
FacetOptions options = new FacetOptions();
options.addFacetOnField(new FieldWithFacetParameters("name").setPrefix("spring"));

4.4.1.范围分面

您可以通过在 上配置所需范围来创建范围分面查询FacetOptions。您可以通过创建FacetOptions实例、将选项设置为 aFacetQuery并通过 查询分面页面来请求范围SolrTemplate,如下所示。

代码语言:javascript复制
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注解查询,如下:

代码语言:javascript复制
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,如下所示:

代码语言:javascript复制
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方法:

代码语言:javascript复制
List<FacetPivotFieldEntry> pivot = facetResult.getPivot(new SimplePivotField("categories","available"));

4.5.条款

术语向量不能直接在其中使用,SolrRepository但可以通过 应用SolrTemplate。请记住,结果是TermsPage. 以下示例显示了如何创建术语查询:

代码语言:javascript复制
TermsQuery query = SimpleTermsQuery.queryBuilder().fields("name").build();
TermsPage page = solrTemplate.queryForTermsPage("collection-1", query);

4.6.结果分组和字段折叠

结果分组不能直接在内部使用,SolrRepository但可以通过 应用SolrTemplate。请记住,结果是GroupPage. 以下示例显示了如何创建结果组:

代码语言:javascript复制
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,如下所示:

代码语言:javascript复制
// 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,如下所示:

代码语言:javascript复制
@Query("name:?0")
@Stats(value = { "price" })
StatsPage<Product> findByName(String name, Pageable page);

还支持不同的计算和分面:

代码语言:javascript复制
// 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();

前面示例的注释(因此更短)版本如下:

代码语言:javascript复制
@Query("name:?0")
@Stats(value = "category", facets = { "availability" }, calcDistinct = true)
StatsPage<Product> findByName(String name);

为了执行选择性分面或选择性不同计算,您可以使用@SelectiveStats,如下所示:

代码语言:javascript复制
// 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 中,除非另有说明,所有距离单位都是公里,点的单位是纬度和经度。

以下示例显示了地理点(在本例中为奥地利)的过滤器查询:

代码语言:javascript复制
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允许您定义使用输入参数作为值的占位符。

以下示例显示了带有占位符 ( :)的查询:

代码语言:javascript复制
@Query(value = "*:*", filters = { "inStock:true", "popularity:[* TO 3]" })
List<Product> findAllFilterAvailableTrueAndPopularityLessThanEqual3();

0 人点赞