如果之前没有返回具有相同值的另一个结果(例如 locationName),有没有办法让 SearchSession 只返回一个结果?
不是真的,至少不是at the moment。
如果您使用的是 Elasticsearch 后端并且可以很好地使用本机,您可以insert native JSON into the Elasticsearch request,尤其是collapsing。
我认为这样的事情可能会奏效:
SearchResult<Location> result = searchSession.search( Location.class )
.extension( ElasticsearchExtension.get() )
.where( f -> f.bool()
.must( f.match()
.field("locationName")
.matching((phrase)).fuzzy())
)
.requestTransformer( context -> {
JsonObject collapse = new JsonObject();
collapse.addProperty("field", "locationName_keyword")
JsonObject body = context.body();
body.add( "collapse", collapse );
} )
// You probably need a sort, as well:
.sort(f -> f.field("id"))
.fetch( page * limit, limit );
您需要将locationName_keyword 字段添加到您的Location 实体:
@Indexed
@Entity
public class Location {
// ...
@Id
@GenericField(sortable = Sortable.YES) // Add this
private Long id;
// ...
@FullTextField
@KeywordField(name = "locationName_keyword", sortable = Sortable.YES) // Add this
private String locationName;
// ...
}
(您可能还需要将 custom normalizer 分配给 locationName_keyword 字段,如果重复位置的 locationName 略有不同(不同的情况,...))
但请注意,搜索结果中的“总命中数”将指示命中数前崩溃。因此,如果只有一个匹配的 locationName,但有 5 个具有该名称的 Location 实例,则总命中数将为 5,但用户只会看到一个命中。他们肯定会感到困惑。
话虽如此,可能值得再看看你的情况,以确定这里是否真的需要折叠:
结果,当我们尝试在应用程序的 UI 上显示它们时,看起来好像有重复的值,即使它们在数据库中是唯一的。
如果您有多个具有相同locationName 的文档,那么您在数据库中肯定有多个具有相同locationName 的行吗?索引时不会自发出现重复。
我想说要做的第一件事是退后一步,考虑您是否真的要查询Location 实体,或者另一个相关实体是否更有意义。当两个位置具有相同的名称时,它们是否与另一个公共实体实例有关系(例如,Shop 类型,...)?
=> 如果是这样,您可能应该查询该实体类型(.search(Shop.class)),并利用@IndexedEmbedded 允许基于Location 属性的过滤(即添加@IndexedEmbedded 到@ 中的location 关联987654344@ 实体类型,然后在添加应与位置名称匹配的谓词时使用字段location.locationName)。
如果没有这样相关的通用实体实例,那么我会尝试找出为什么位置会完全重复,更重要的是为什么重复在数据库中有意义,但对用户没有意义:
- 用户是否不感兴趣全部地点?那么也许您应该向您的查询添加另一个过滤器(通过“类型”,...),这将有助于删除重复项。如有必要,您甚至可以运行多个搜索查询:第一个具有非常严格的过滤器,如果没有命中,则回退到另一个过滤器不太严格的搜索查询。
- 您是否在使用某种版本控制或软删除?那么也许你应该避免索引软删除的实体或旧版本;您可以使用conditional indexing 来做到这一点,或者,如果这不起作用,请在搜索查询中使用过滤器。
如果您的数据确实是重复的(遗留数据库,...),除了“只选择第一个”之外,没有任何方法可以选择重复,您可以考虑是否需要聚合而不是全面搜索。您只是在寻找最热门的地点名称,还是按名称查找地点数量?那么聚合是正确的工具。