英文:
Hibernate search - cconvert sql to lucene query
问题
我有以下的选择SQL查询:
SELECT * FROM data_entity WHERE
agreement_number='9999' AND use_type='xxxx' AND end_date IS NOT NULL AND end_date <= '2022-05-03'::date
OR (rib='1111111' AND iban='22222222');
我想将其转换为使用Hibernate Search的查询。我尝试了以下查询,但它没有给我正确的结果,有人可以看到查询可能出了什么问题吗?
@Entity
@Indexed
public class DataEntity {
@Id
private String id;
@Field
private String agreementNumber;
@Field
private String useType;
@Field
@DateBridge(resolution = Resolution.DAY)
private Date endDate;
@Field
private String rib;
@Field
private String iban;
}
org.apache.lucene.search.Query firstQuery = getQuery().bool()
.must(getQuery().bool()
.must(getQuery().keyword().onField("agreementNumber").matching(agreementNumber).createQuery())
.must(getQuery().keyword().onField("useType").matching(useType).createQuery())
.must(getQuery().range().onField("endDate").above(effectiveDate).createQuery()).createQuery())
.should(getQuery().bool()
.must(getQuery().keyword().onField("rib").matching(rib).createQuery())
.must(getQuery().keyword().onField("iban").matching(iban).createQuery()).createQuery())
.createQuery();
英文:
I have the below select SQL query
SELECT * FROM data_entity WHERE
agreement_number='9999' AND use_type='xxxx' AND end_date IS NOT NULL AND end_date <= '2022-05-03'::date
OR (rib='1111111' AND iban='22222222');
I want to convert it to query using hibernate search, i tried with the below query, but it doesn't give me the right result, can anyone see what can be the problem with the query?
@Entity
@Indexed
public class DataEntity {
@Id
private String id;
@Field
private String agreementNumber;
@Field
private String useType;
@Field
@DateBridge(resolution = Resolution.DAY)
private Date endDate;
@Field
private String rib;
@Field
private String iban;
}
org.apache.lucene.search.Query firstQuery = getQuery().bool()
.must(getQuery().bool()
.must(getQuery().keyword().onField("agreementNumber").matching(agreementNumber).createQuery())
.must(getQuery().keyword().onField("useType").matching(useType).createQuery())
.must(getQuery().range().onField("endDate").above(effectiveDate).createQuery()).createQuery())
.should(getQuery().bool()
.must(getQuery().keyword().onField("rib").matching(rib).createQuery())
.must(getQuery().keyword().onField("iban").matching(iban).createQuery()).createQuery())
.createQuery();
答案1
得分: 1
你正在同一个布尔查询中使用了 must
和 should
。这可能不会产生你期望的结果。
要模拟布尔 AND
,请使用仅包含 must
子句的布尔查询。
要模拟布尔 OR
,请使用仅包含 should
子句的布尔查询。
另外,你正在使用 above
来比较日期,但是你的 SQL 查询明显是在寻找给定日期之前的日期。
所以,尝试这样做:
org.apache.lucene.search.Query firstQuery = getQuery().bool()
.should(getQuery().bool()
.must(getQuery().keyword().onField("agreementNumber").matching(agreementNumber).createQuery())
.must(getQuery().keyword().onField("useType").matching(useType).createQuery())
.must(getQuery().range().onField("endDate").below(effectiveDate).createQuery()).createQuery())
.should(getQuery().bool()
.must(getQuery().keyword().onField("rib").matching(rib).createQuery())
.must(getQuery().keyword().onField("iban").matching(iban).createQuery()).createQuery())
.createQuery();
另外,你可能还想禁用代表代码的字段的分析,比如 agreementNumber
、rib
等。否则,你可能会得到比预期更多的匹配项。或者,如果你需要一定程度的宽松性,但不需要完全的分析,你可以依赖于 normalizers
:https://docs.jboss.org/hibernate/search/5.11/reference/en-US/html_single/#section-normalizers
(对于其他人阅读此内容,"RIB" 是法国的银行账户标识符,不是一块肉)
英文:
You're using must
and should
in the same boolean query. This probably won't do what you think it will.
To emulate a boolean AND
, use a boolean query with only must
clauses.
To emulate a boolean OR
, use a boolean query with only should
clauses.
Also, you're using above
to compare the date, while your SQL query is clearly looking for dates before the given date.
So, try that:
org.apache.lucene.search.Query firstQuery = getQuery().bool()
.should(getQuery().bool()
.must(getQuery().keyword().onField("agreementNumber").matching(agreementNumber).createQuery())
.must(getQuery().keyword().onField("useType").matching(useType).createQuery())
.must(getQuery().range().onField("endDate").below(effectiveDate).createQuery()).createQuery())
.should(getQuery().bool()
.must(getQuery().keyword().onField("rib").matching(rib).createQuery())
.must(getQuery().keyword().onField("iban").matching(iban).createQuery()).createQuery())
.createQuery();
On a related note, you may also want to disable analysis on fields that represents codes, such as agreementNumber
, rib
, etc. Otherwise you may end up with more matches than you intended. Alternatively, if you need some level of leniency, but not full-blown analysis, you can rely on normalizers
: https://docs.jboss.org/hibernate/search/5.11/reference/en-US/html_single/#section-normalizers
(for anyone else reading this, a "RIB" is a French bank account identifier, not a chunk of meat)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论