我想使用休眠搜索Elasticsearch库实现某种“随机”排序。我在做什么如下:
实现FieldComparator:
public class RandomOrderFieldComparator extends FieldComparator<Integer> {
private final Random randomGenerator = new Random();
@Override
public int compare(int slot1, int slot2) {
return randomGenerator.nextInt();
}
@Override
public void setTopValue(Integer value) {
//not needed as the purpose is to generate random integers w
}
@Override
public Integer value(int slot) {
return randomGenerator.nextInt();
}
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
return null;
}
}
Implement FieldComparatorSource
public class SampleFieldComparatorSource extends FieldComparatorSource {
@Override
public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {
return new RandomOrderFieldComparator();
}
}
最后创建一个提供FieldComparatorSource的自定义SortField:
queryBuilder
.sort()
.byNative(
new SortField(
"id",
new SampleFieldComparatorSource()
)
);
问题是它仍然仅使用'id'字段上的常规排序来生成查询,并且从未命中比较器:
"sort": [
{
"id": {
"order": "asc"
}
}
]
我在做什么错,使用休眠搜索库实现“随机”排序的最佳方法是什么?
实际上,我找到了一种通过直接通过JSON并使用无痛脚本进行休眠搜索的方法:
queryBuilder.sort()
.byNative("_script", "{"
+ "\"type\" : \"number\","
+ "\"script\" : {"
+ " \"lang\": \"painless\","
+ " \"source\": \"new Random().nextInt()\""
+ "},"
+ "\"order\" : \"asc\""
+ "}");
Elasticsearch集成通过将Lucene对象转换为JSON并将其发送到Elasticsearch集群来工作。它适用于简单的事情,例如按字段值排序,术语查询等,但绝对不能转换您自己实现的Java对象。
简而言之,一旦您使用Lucene接口的自定义实现,就可以确定它不适用于Elasticsearch集成。因此,您的RandomOrderFieldComparator
无效。
[如果您需要执行Hibernate Search无法通过其API公开的高级内容,例如这种随机排序,则您必须自己编写发送给Elasticsearch的JSON。 Stackoverflow为该问题提供了various solutions。
编辑:我其余的答案是错误的。我忘记了本机排序功能,可惜了。参见other answer
我无法使用Hristo Angelov的答案来进行分页工作。我曾尝试使用new Random(long).nextInt()
,但无论种子值如何,它都始终生成相同的顺序。按照link in yrodiere's answer的指示,我找到了这个解决方案,该解决方案完美无缺。
String fieldName = "id"; //replace with your search field
String seed = "hello world"; //generate a random string that persists across pages of the same search
sort = qb.sort()
.byNative("_script",
"{"
+ "\"script\" : \"(doc['" + fieldName + "'].value + '" + seed + "').hashCode()\","
+ "\"type\" : \"number\","
+ "\"order\" : \"asc\""
+ "}")
.createSort();