我正在使用 spring-data-elasticsearch(最新版本)和 elasticsearch 的 docker 實體(最新版本),我想在查詢后從我的存盤庫回傳的所有結果上計算一個欄位。我不想在存盤庫中提供這些資訊,因為它有時依賴于查詢,有時依賴于環境。例如,如果我們執行查詢,我想生成一個 URL,其中包含查詢詞作為 URL 中的查詢引數,我想用它來豐富結果。還有一些其他情況。我嘗試創建一個接受整個檔案物件的彈簧資料自定義閱讀轉換器。我可以看到它在應用程式啟動時被識別,但它從未被呼叫。如何使用自定義值投影欄位,或使用背景關系計算值豐富回傳的檔案?
uj5u.com熱心網友回復:
我首先想到了AfterConvertCallback像 Chin 評論的那樣,但是在回呼中,您沒有為獲取物體而運行的查詢的背景關系,因此您不能使用諸如查詢術語之類的東西來構建某些東西。
我會添加屬性 - 讓我們在這里命名它url的型別String- 到物體并用org.springframework.data.annotation.Transient注釋標記它以防止它被存盤。
然后在您進行搜索的方法中,使用ElasticsearchOperations或存盤庫,對回傳的物體進行后處理(代碼未測驗,只是寫在這里):
SearchHits<Entity> searchHits = repository.findByFoo(String fooValue);
searchHits.getSearchHits().forEach(searchHit -> {
searchHit.getContent().setUrl(someValueDerivedFromEnvironemtAndQuery);
});
之后繼續使用SearchHits.
uj5u.com熱心網友回復:
我喜歡結合@ChinHuang 和@PJMeisch 的答案的混合方法。根據背景關系或情況,這兩個答案都有其適用性。我喜歡 Chin Huang 對基于實體的資訊的建議,在那里你需要配置值之類的東西。我也同意 PJ Meisch 是正確的,他擔心這不會讓您訪問立即查詢,所以我喜歡他在從資料存盤回傳資料時攔截/映射值的想法。我很欣賞兩個人提供的重要資訊,因為這兩種方法的結合是我很滿意的解決方案。
我更喜歡盡可能使用存盤庫介面,因為許多人錯誤地將業務邏輯混合到他們的存盤庫中。如果我想要自定義實作,那么我不得不真正考慮它,因為我必須創建一個“Impl”類來實作它。這不是最嚴重的錯誤,但我總是為存盤庫提供業務服務,該服務負責任何資料整理,或任何非嚴格檢索或持久性資料的程式化操作。
這是我創建自定義AfterConvertCallback. 我在onAfterConvert方法中設定了基本 URL :
@Bean
AfterConvertCallback<BookInfo> bookInfoAfterConvertCallback() {
return new BookInfoAfterConvertCallback(documentUrl);
}
static class BookInfoAfterConvertCallback implements AfterConvertCallback<BookInfo> {
private final String documentUrl;
public BookInfoAfterConvertCallback(String documentUrl) {
this.documentUrl = documentUrl;
}
@Override
public BookInfo onAfterConvert(final BookInfo entity, final Document document, final IndexCoordinates indexCoordinates) {
entity.setUrl(String.format("%s?id=%d", documentUrl, entity.getId()));
return entity;
}
}
在呼叫存盤庫查詢的資料服務中,我撰寫了一對函式來創建 URL 的查詢引數部分,以便我可以將它附加到任何使用自動連接存盤庫實體的適用方法中:
/**
* Given a term, encode it so that it can be used as a query parameter in a URL
*/
private static final Function<String, String> encodeTerm = term -> {
try {
return URLEncoder.encode(term, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
log.warn("Could not encode search term for document URL", e);
return null;
}
};
/**
* Given a list of search terms, transform them into encoded URL query parameters and append
* them to the given URL.
*/
private static final BiFunction<List<String>, String, String> addEncodedUrlQueryParams = (searchTerms, url) ->
searchTerms.stream()
.map(term -> String.format("term=%s", encodeTerm.apply(term)))
.filter(Objects::nonNull)
.collect(Collectors.joining("&", url "&", ""));
這絕對可以在存盤庫實體或其封閉服務中完成。但是,當您想要攔截檢索到的所有資料,并對其進行一些不特定于查詢的操作時,回呼是一個很好的選擇,因為它不會產生需要在每個資料層中引入它的維護成本它應該適用的方法。在查詢時,當您需要參考僅在查詢中可用的資訊時,顯然將這種型別的代碼引入到您的資料層(服務或存盤庫)方法中。
I am adding this as an answer because, even though I didn't realize it at the time that I posted my question, this is two concerns that are separate enough to warrant both approaches. I do not want to claim credit for this answer, so I will not select it as the answer unless you both comment on this, and tell me that you want me to do that.
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/352733.html
