我正在使用休眠搜索來構造一個 lucene 查詢,該查詢回傳包含(部分)搜索字串的字串值。接下來,如果語言 id 也匹配并且洗掉標志未設定為 true,則查詢必須僅回傳字串值。我為此撰寫了以下代碼。但問題是它不回傳任何東西。
private Query getQueryWithBooleanClauses(Class entityClass, String searchString, Long preferredLanguageId, FullTextEntityManager fullTextEntityManager, String firstField, String... additionalFields) {
QueryBuilder queryBuilder = getQueryBuilder(entityClass, fullTextEntityManager);
Query containsSearchString = getMatchingStringCondition(searchString, queryBuilder, firstField, additionalFields);
BooleanQuery isPreferredOrDefaultLanguageTranslation = getLanguageCondition(preferredLanguageId);
BooleanQuery finalQuery = new BooleanQuery.Builder()
.add(new TermQuery(new Term("parentDeleted", "false")), BooleanClause.Occur.MUST)
.add(new TermQuery(new Term("parentApproved", "true")), BooleanClause.Occur.MUST)
.add(new TermQuery(new Term("childDeleted", "false")), BooleanClause.Occur.MUST)
.add(isPreferredOrDefaultLanguageTranslation, BooleanClause.Occur.MUST)
.add(containsSearchString, BooleanClause.Occur.MUST)
.build();
return finalQuery;
}
獲取匹配字串條件
private Query getMatchingStringCondition(String searchString, QueryBuilder queryBuilder, String firstField, String... additionalFields) {
log.info(MessageFormat.format("{0}*", searchString));
return queryBuilder.simpleQueryString()
.onFields(firstField, additionalFields)
.withAndAsDefaultOperator()
.matching(MessageFormat.format("{0}*", searchString))
.createQuery();
}
獲取語??言條件
private BooleanQuery getLanguageCondition(Long preferredLanguageId) {
return new BooleanQuery.Builder()
.add(createLanguagePredicate(preferredLanguageId), BooleanClause.Occur.SHOULD)
.add(createLanguagePredicate(languageService.getDefaultLanguage().getId()), BooleanClause.Occur.SHOULD)
.build();
}
創建語言謂詞
private Query createLanguagePredicate(Long languageId){
return new TermQuery(new Term("language.languageId", languageId.toString()));
}
查詢執行方法
public List<AutoCompleteSuggestion> findAllBySearchStringAndDeletedIsFalse(Class entityClass, String searchString, Long preferredLanguageId){
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
Query finalQuery = getQueryWithBooleanClauses(entityClass, searchString, preferredLanguageId, fullTextEntityManager, "parent.latinName", "translatedName");
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(finalQuery, entityClass);
fullTextQuery.setProjection("parentId", "autoCompleteSuggestion", "childApproved"); //volgorde moet overeen komen met argumenten volgorde in AutoCompleteSuggestion constructor, zie convertToAutoCompleteSuggestionList
fullTextQuery.setMaxResults(maxResults);
fullTextQuery.getResultList();
return convertToAutoCompleteSuggestionList(fullTextQuery.getResultList());
}
此代碼不會引發錯誤,但也不會回傳任何內容。只有當我洗掉布爾和數字欄位的所有布爾條件時,只留下containsSearchString條件,查詢才會回傳任何內容。
According to this post Hibernate Search 5.0 Numeric Lucene Query HSEARCH000233 issue this happens because as of Hibernate search 5 numerical fields are no longer treated as text fields and you can't perform matching queries on numerical fields.
You can force that the fields are treated as textfields by annotating them with @FieldBridge. But i'd rather not do that. So my question is. How do i perform match queries on non-text fields like booleans, dates, and numbers?
EDIT: It works if i annotate all the fields required for filtering with @FieldBridge(impl= implementation.class)`,also the index parameter must always be set to YES.
But now all these fields will be stored as strings, which is undesirable. So i'd still like to know if there is another more elegant way to apply filters.
EDIT 2:
@yrodiere, When i removed @FieldBridge(impl = LongBridge.class) from languageId and replace the line .add(isPreferredOrDefaultLanguageTranslation, BooleanClause.Occur.MUST) with:
.add(queryBuilder.bool().must(queryBuilder.keyword().onField("language.languageId").matching(languageService.getDefaultLanguage().getId().toString()).createQuery()).createQuery(), BooleanClause.Occur.MUST)
I get the error:
org.hibernate.search.exception.SearchException: HSEARCH000238: Cannot create numeric range query for field 'language.languageId', since values are not numeric (Date, int, long, short or double)
However just now i discovered that matching() also accepts a Long number so i don't have to call toString() on it. When matching() uses the Long value i don't get an error but nothing is returned either.
Only when i used new TermQuery(new Term("language.languageId", languageId.toString())) instead of matching() while also using a LongBridge for languageId will anything get returned. Am i defining the matching() query erroneously?
I also have a different question that i wanted to start a new SO question for. But maybe you can answer that question in this thread as well :). The question is about the includeEmbeddedObjectId parameter of @IndexedEmbedded. I think i know what this does but i would like to have some confirmation from you.
我假設當我將此設定true為父物體的 id 時,將包含在子物體的 lucene 檔案中,對嗎?假設此父物體matching()用于用作true/false條件的查詢中。那么假設搜索會更快,因為現在也可以在子物體的 lucene 檔案中找到 id 是否正確?
謝謝
uj5u.com熱心網友回復:
在 Hibernate Search 5 中,布林值仍被索引為字串。請參閱org.hibernate.search.bridge.builtin.BooleanBridge。所以布爾欄位不是這里問題的一部分。
如果你真的想自己創建數字查詢,在 Hibernate Search 5 中你將不得不使用數字范圍查詢,例如:
private Query createLanguagePredicate(Long languageId){
return org.apache.lucene.search.NumericRangeQuery.newLongRange("language.languageId", languageId,
languageId, true, true);
}
話雖如此,為了避免此類問題,您應該使用Hibernate Search DSL。然后,您將傳遞您在模型中使用的型別的值(此處為 a Long),Hibernate Search 將自動創建正確的查詢。
或者更好的是,升級到Hibernate Search 6,它公開了一個不同的 API,但不那么冗長,也有更少的怪癖。在 Hibernate Search 6 中的 Search DSL 檔案中親自查看,特別是謂詞 DSL。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/357697.html
