Hibernate搜索 – 将SQL转换为Lucene查询

huangapple go评论81阅读模式
英文:

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=&#39;9999&#39; AND use_type=&#39;xxxx&#39; AND end_date IS NOT NULL AND end_date &lt;= &#39;2022-05-03&#39;::date 
OR (rib=&#39;1111111&#39; AND iban=&#39;22222222&#39;);

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(&quot;agreementNumber&quot;).matching(agreementNumber).createQuery())
		.must(getQuery().keyword().onField(&quot;useType&quot;).matching(useType).createQuery())
		.must(getQuery().range().onField(&quot;endDate&quot;).above(effectiveDate).createQuery()).createQuery())
	.should(getQuery().bool()
		.must(getQuery().keyword().onField(&quot;rib&quot;).matching(rib).createQuery())
		.must(getQuery().keyword().onField(&quot;iban&quot;).matching(iban).createQuery()).createQuery())
        .createQuery();

答案1

得分: 1

你正在同一个布尔查询中使用了 mustshould。这可能不会产生你期望的结果。

要模拟布尔 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();

另外,你可能还想禁用代表代码的字段的分析,比如 agreementNumberrib 等。否则,你可能会得到比预期更多的匹配项。或者,如果你需要一定程度的宽松性,但不需要完全的分析,你可以依赖于 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(&quot;agreementNumber&quot;).matching(agreementNumber).createQuery())
        .must(getQuery().keyword().onField(&quot;useType&quot;).matching(useType).createQuery())
        .must(getQuery().range().onField(&quot;endDate&quot;).below(effectiveDate).createQuery()).createQuery())
    .should(getQuery().bool()
        .must(getQuery().keyword().onField(&quot;rib&quot;).matching(rib).createQuery())
        .must(getQuery().keyword().onField(&quot;iban&quot;).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)

huangapple
  • 本文由 发表于 2020年8月12日 17:51:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/63374039.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定