8

Hibernate Search Query DSLを学んでいますが、AND や OR などのブール引数を使用してクエリを作成する方法がわかりません。

firstNameたとえば、 "bill" または "bob"の値を持つすべての人物レコードを返したいとします。

hibernate のドキュメントに従って、次のような 2 つのサブクエリで bool() メソッドを使用する例を 1 つ示します。

QueryBuilder b = fts.getSearchFactory().buildQueryBuilder().forEntity(Person.class).get();
Query luceneQuery = b.bool()
    .should(b.keyword().onField("firstName").matching("bill").createQuery())
    .should(b.keyword().onField("firstName").matching("bob").createQuery())
    .createQuery();

logger.debug("query 1:{}", luceneQuery.toString());

これにより、最終的に必要な lucene クエリが生成されますが、これはブール値ロジックを休止状態検索で使用する適切な方法ですか? 「should()」は「OR」と同等ですか (同様に、「must()」は「AND」に対応しますか)?

また、この方法でクエリを作成するのは面倒です。たとえば、照合する firstNames のコレクションがある場合はどうなるでしょうか。そもそも、このタイプのクエリは DSL に適しているのでしょうか?

4

4 に答える 4

3

はい、あなたの例は正しいです。ブール演算子は、Lucene APIとドキュメントにある名前のため、またより適切であるため、ORの代わりにshouldと呼ばれます。ブール演算子は、ブール決定に影響を与えるだけでなく、結果のスコアリングにも影響します。

たとえば、「ブランドFiat」または「blue」の車を検索すると、Fiat AND blueのブランドの車も返され、青いがFiatではない車よりもスコアが高くなります。

プログラマティックであり、多くの詳細なオプションを提供するため、面倒に感じるかもしれません。より簡単な代替方法は、クエリに単純な文字列を使用し、QueryParserを使用してクエリを作成することです。一般に、パーサーはユーザー入力を解析するのに役立ちます。プログラムによるパーサーは、明確に定義されたフィールドを処理する方が簡単です。たとえば、あなたが言及したコレクションがある場合、forループでそれを構築するのは簡単です。

于 2012-04-25T19:54:31.033 に答える
2

BooleanQueryも使用できます。リストのループでこれを使用できるので、私はこれを好むでしょう。

    org.hibernate.search.FullTextQuery hibque = null; 

    org.apache.lucene.search.BooleanQuery bquery = new BooleanQuery();

    QueryBuilder qb = fulltextsession.getSearchFactory().buildQueryBuilder()
              .forEntity(entity.getClass()).get();
    for (String keyword : list) {
        bquery.add(qb.keyword().wildcard().onField(entityColumn).matching(keyword)
              .createQuery()  , BooleanClause.Occur.SHOULD);
    }

    if (!filterColumn.equals("") && !filterValue.equals("")) {
       bquery.add(qb.keyword().wildcard().onField(column).matching(value).createQuery()
                        , BooleanClause.Occur.MUST);
    } 

    hibque = fulltextsession.createFullTextQuery(bquery, entity.getClass());

    int num = hibque.getResultSize();
于 2015-03-10T06:30:33.560 に答える
1

二次的な質問に答えるには:

たとえば、照合する firstNames のコレクションがある場合はどうなるでしょうか。

私は専門家ではありませんが、(最後の 3 番目の例) 5.1.2.1 によると。Hibernate Search Documentationのキーワード クエリでは、次のようにクエリを作成できるはずです。

Collection<String> namesCollection = getNames(); // Contains "billy" and "bob", for example
StringBuilder names = new StringBuilder(100);
for(String name : namesCollection) {
    names.append(name).append(" "); // Never mind the space at the end of the resulting string.
}

QueryBuilder b = fts.getSearchFactory().buildQueryBuilder().forEntity(Person.class).get();
Query luceneQuery = b.bool()
    .should(
        // Searches for multiple possible values in the same field
        b.keyword().onField("firstName").matching( sb.toString() ).createQuery()
    )
    .must(b.keyword().onField("lastName").matching("thornton").createQuery())
    .createQuery();

そして、結果として、Persons with (firstName できれば"billy" または "bob") AND ( lastName= "thornton") が得られますが、古き良きビリー・ボブ・ソーントンに高いスコアを与えるとは思いません ;-)。

于 2012-11-24T08:09:16.667 に答える
1

私は同じ問題を探していましたが、提示されたものとは多少異なる問題があります。OR私は実際のジャンクションを探していました。結果は2つの式のいずれにも合格しなかったが、スコアが低かったため、はずのケースはうまくいきませんでした。これらの結果を完全に省略したかったのです。ただし、スコアリングを無効にする別のブール式を使用して、実際のブール OR 式を作成できます。

val booleanQuery = cb.bool();
val packSizeSubQuery = cb.bool();

packSizes.stream().map(packSize -> cb.phrase()
     .onField(LUCENE_FIELD_PACK_SIZES)
     .sentence(packSize.name())
     .createQuery())
     .forEach(packSizeSubQuery::should);

booleanQuery.must(packSizeSubQuery.createQuery()).disableScoring();
fullTextEntityManager.createFullTextQuery(booleanQuery.createQuery(), Product.class)
return persistenceQuery.getResultList();
于 2016-11-07T17:10:22.890 に答える