英文:
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论