2

Hibernate Search Annotations@Field(index = Index.TOKENIZED)の使用 (ほとんどは . を使用して、インデックス付きのすべてのフィールドに対してテキスト検索をセットアップしましたがMultiFieldQueryParser、これはこれまでのところ正常に機能しています。

索引付けされ、検索可能なフィールドの中には、サンプル値を持つ CompoundName と呼ばれるフィールドがあります。

  • 3-Hydroxyflavone
  • 6,4'-Dihydroxyflavone

これらの値のいずれかを完全に検索すると、関連する複合インスタンスが返されます。ただし、部分的な名前を使用してワイルドカードを導入すると、問題が発生します。

  • を検索して3-Hydroxyflav*も正しいヒットが得られますが、
  • を検索し6,4'-Dihydroxyflav*ても何も見つかりません。

今、私はLucene / Hibernate-searchにまったく慣れていないので、この時点でどこを見るべき'かよくわかりません..2番目のクエリの現在と関係があるのではないかと思いますが、わかりません続行する方法..トークナイザー/アナライザー/クエリパーサーまたは他の何かを完全に調べる必要がありますか?

または、できればマルチフィールド検索の動作を壊さずに、2番目のワイルドカード検索を一致させる方法を教えてもらえますか?

Hibernate-Search 3.1.0.GA と Lucene-core 2.9.3 を使用しています。


私の現在のアプローチを説明するためのいくつかの関連コードビット:

インデックス化された化合物クラスの関連部分:

@Entity
@Indexed
@Data
@EqualsAndHashCode(callSuper = false, of = { "inchikey" })
public class Compound extends DomainObject {
    @NaturalId
    @NotEmpty
    @Length(max = 30)
    @Field(index = Index.TOKENIZED)
    private String                  inchikey;

    @ManyToOne
    @IndexedEmbedded
    private ChemicalClass           chemicalClass;

    @Field(index = Index.TOKENIZED)
    private String                  commonName;
...
}

現在、インデックス付きフィールドを検索する方法:

String[] searchfields = Compound.getSearchfields();
MultiFieldQueryParser parser = 
    new MultiFieldQueryParser(Version.LUCENE_29, searchfields, new StandardAnalyzer(Version.LUCENE_29));
FullTextSession fullTextSession = Search.getFullTextSession(getSession());
FullTextQuery fullTextQuery = 
    fullTextSession.createFullTextQuery(parser.parse("searchterms"), Compound.class);
List<Compound> hits = fullTextQuery.list();
4

3 に答える 3

4

StandardAnalyzer の代わりに WhitespaceAnalyzer を使用します。コンマやハイフンなどではなく、空白で分割されるだけです(ただし、小文字は使用されないため、検索で大文字と小文字を区別しない場合は、空白と小文字の独自のチェーンを構築する必要があります)。フィールドごとに異なる処理を行う必要がある場合は、PerFieldAnalyzer を使用できます。

トークン化されていない状態に設定することはできません。これは、テキスト全体が 1 つのトークンとして解釈されるためです。

于 2010-09-24T13:20:15.970 に答える
2

あなたの問題は、アナライザーとクエリ言語の問題の組み合わせだと思います。問題の正確な原因を特定することは困難です。これを見つけるには、Lucene インデックス ツールLukeを使用してインデックスを調べることをお勧めします。

Hibernate Search 設定ではカスタム アナライザーを使用していないため、デフォルトのStandardAnalyzerが使用されます。これは、 MultiFieldQueryParserのコンストラクターでStandardAnalyzerを使用するという事実と一致します(インデックス作成と検索には常に同じアナライザーを使用してください!)。私が確信していないのは、「6,4'-ジヒドロキシフラボン」がStandardAnalyzerによってどのようにトークン化されるかです。それはあなたが見つけなければならない最初のことです。たとえば、javadoc には次のように書かれています。

トークンに数字が含まれていない限り、単語をハイフンで分割します。数字が含まれている場合、トークン全体が製品番号として解釈され、分割されません。

ユースケースに必要な方法で化学名をトークン化する独自のアナライザーを作成する必要があるかもしれません。

次に、クエリ パーサーです。クエリ構文 ( Lucene クエリ構文) を理解していることを確認してください。「-」など、一部の文字には特別な意味があります。クエリが間違った方法で解析されている可能性があります。

いずれにせよ、最初のステップは、化学名がどのようにトークン化されるかを調べることです。それが役立つことを願っています。

于 2010-09-24T08:46:37.677 に答える
1

私は自分のアナライザーを書きました:

import java.util.Set;
import java.util.regex.Pattern;

import org.apache.lucene.index.memory.PatternAnalyzer;
import org.apache.lucene.util.Version;

public class ChemicalNameAnalyzer extends PatternAnalyzer {

    private static Version version = Version.LUCENE_29;
    private static Pattern pattern = compilePattern();
    private static boolean toLowerCase = true;
    private static Set stopWords = null;

    public ChemicalNameAnalyzer(){
        super(version, pattern, toLowerCase, stopWords);
    }

    public static Pattern compilePattern() {
        StringBuilder sb =  new StringBuilder();
        sb.append("(-{0,1}\\(-{0,1})");//Matches an optional dash followed by an opening round bracket followed by an optional dash  
        sb.append("|");//"OR" (regex alternation)
        sb.append("(-{0,1}\\)-{0,1})"); 
        sb.append("|");//"OR" (regex alternation)
        sb.append("((?<=([a-zA-Z]{2,}))-(?=([^a-zA-Z])))");//Matches a dash ("-") preceded by two or more letters and succeeded by a non-letter
        return Pattern.compile(sb.toString());
    }
}
于 2011-03-24T12:11:54.533 に答える