我们正在实现一个全局搜索,可用于查询应用程序中的所有实体,例如cars、books和movies。这些实体不共享公共字段,例如,cars有一个manufacturer,books有一个author,movies有一个director。
在全局搜索字段中,我想通过一个查询搜索所有实体,以便能够使用分页。在考虑如何解决这个问题时,我想到了两种方法:
我现在的问题是:还有第三种(更好的)方法吗?您建议如何在多个索引上实现这样的全局搜索?
逐个查询索引并手动合并结果。这意味着我必须自己实现分页。
我绝对不会这样做,因为这会表现得很差,尤其是深度分页(第 40 页等)。
向每个项目添加公共字段,例如名称和创建者(或创建一个界面,如 Hibernate 搜索中的单一返回类型所示)。在这种情况下,我只能在全局搜索中搜索映射到公共字段的字段。
就是这样。您甚至不需要通用接口,因为您只需在同一个谓词中定位多个字段。通用接口只会帮助定位所有相关类型:您可以调用
.search(MyInterface.class)
而不是 .search(Arrays.asList(Car.class, Book.class, Movie.class))
。
您仍然可以将谓词应用于特定于每种类型的字段;只是以多种类型出现的字段必须一致(相同类型等)。另外,显然,如果您要求“制造商”(并且没有其他字段)匹配“詹姆斯”,则书籍和电影将不再匹配,因为它们没有制造商。
你尝试过吗?例如,只要
manufacturer
、author
和 director
都是具有相同分析器的文本字段,就可以正常工作:
SearchResult<Object> result = searchSession.search( Arrays.asList(
Car.class, Book.class, Movie.class
) )
.where( f -> f.simpleQueryString()
.fields( "manufacturer", "author", "director" )
.matching( "james" ) )
.fetch( 20 );
List<Object> hits = result.hits(); // Result is a mix of Car, Book and Movie.
一种方法是创建一个 SQL 视图(SearchEntry?),它组合了您要搜索的所有表。这允许您为不同的列名称添加别名。这对性能来说不是很好,但您也可以创建一个由不同可搜索字段串联而成的大字段。最后,包括一个与您的实体相关联的“类型”字段。
现在您可以一次性查询所有内容,并使用类型/ID 绑定到最初从中提取“搜索”数据的特定实体。