簡體   English   中英

在休眠搜索elasticsearch中實現“隨機”排序

[英]Implement "random" sort in hibernate search 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"
      }
    }
  ]

我做錯了什么,使用休眠搜索庫實現“隨機”排序的最佳方法是什么?

實際上,我找到了一種方法,通過休眠搜索直接傳遞一個 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 為該問題提供了各種解決方案

編輯:我的其余答案是錯誤的。 我已經忘記了本地排序功能,真丟人。 另一個回答

我無法使用 Hristo Angelov 的答案進行分頁工作。 我曾嘗試使用new Random(long).nextInt()但無論種子值如何,它都保持生成相同的順序。 按照yrodiere 的回答中鏈接,我找到了這個解決方案,它完美無缺。

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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM