我想使用休眠搜索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;
}
}
实施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"
}
}
]
我在做什么错?使用休眠搜索库实现“随机”排序的最佳方法是什么?
答案 0 :(得分:1)
Elasticsearch集成通过将Lucene对象转换为JSON并将其发送到Elasticsearch集群而起作用。它适用于简单的事情,例如按字段值排序,术语查询等,但绝对不能转换您自己实现的Java对象。
简而言之,一旦您使用Lucene接口的自定义实现,就可以确定它无法与Elasticsearch集成一起使用。因此,您的RandomOrderFieldComparator
无法正常工作。
如果您需要执行Hibernate Search不会通过其API公开的高级内容(例如这种随机排序),则必须自己编写发送给Elasticsearch的JSON。 Stackoverflow为该问题提供了various solutions。
编辑:我其余的答案是错误的。我已经忘记了本机排序功能,可惜了。参见other answer
答案 1 :(得分:1)
实际上,我找到了一种通过休眠搜索直接传递JSON并使用无痛脚本的方法:
queryBuilder.sort()
.byNative("_script", "{"
+ "\"type\" : \"number\","
+ "\"script\" : {"
+ " \"lang\": \"painless\","
+ " \"source\": \"new Random().nextInt()\""
+ "},"
+ "\"order\" : \"asc\""
+ "}");
答案 2 :(得分:0)
使用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();