7

指定された入力に基づいてタイトルフィールドを検索する検索ボックスがあるので、ユーザーは挿入されたテキストから始まるすべての利用可能なタイトルを推奨しました。これはLuceneおよびHibernateSearchに基づいています。スペースが入るまでは問題なく動作します。その後、結果は消えます。たとえば、「Learning H」で、結果として「LearningHibernate」を取得したいと思います。ただし、これは発生しません。代わりにここで何を使うべきかアドバイスしていただけませんか。

クエリビルダー:

QueryBuilder qBuilder = fullTextSession.getSearchFactory()
        .buildQueryBuilder().forEntity(LearningGoal.class).get();
  Query query = qBuilder.keyword().wildcard().onField("title")
        .matching(searchString + "*").createQuery();

  BooleanQuery bQuery = new BooleanQuery();
  bQuery.add(query, BooleanClause.Occur.MUST);
  for (LearningGoal exGoal : existingGoals) {
     Term omittedTerm = new Term("id", String.valueOf(exGoal.getId()));
     bQuery.add(new TermQuery(omittedTerm), BooleanClause.Occur.MUST_NOT);
  }
  @SuppressWarnings("unused")
  org.hibernate.Query hibQuery = fullTextSession.createFullTextQuery(
        query, LearningGoal.class);

Hibernateクラス

@AnalyzerDef(name = "searchtokenanalyzer",tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
  @TokenFilterDef(factory = StandardFilterFactory.class),
  @TokenFilterDef(factory = LowerCaseFilterFactory.class),
  @TokenFilterDef(factory = StopFilterFactory.class,params = { 
      @Parameter(name = "ignoreCase", value = "true") }) })
      @Analyzer(definition = "searchtokenanalyzer")
public class LearningGoal extends Node {
4

2 に答える 2

9

この問題の回避策を見つけました。アイデアは、入力文字列をトークン化し、ストップワードを削除することです。最後のトークンでは、キーワードワイルドカードを使用してクエリを作成し、それ以前のすべての単語では、TermQueryを作成しました。これが完全なコードです

    BooleanQuery bQuery = new BooleanQuery();
    Session session = persistence.currentManager();
    FullTextSession fullTextSession = Search.getFullTextSession(session);
    Analyzer analyzer = fullTextSession.getSearchFactory().getAnalyzer("searchtokenanalyzer");
    QueryParser parser = new QueryParser(Version.LUCENE_35, "title", analyzer);
    String[] tokenized=null;
    try {
    Query query=    parser.parse(searchString);
    String cleanedText=query.toString("title");
     tokenized = cleanedText.split("\\s");

    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    QueryBuilder qBuilder = fullTextSession.getSearchFactory()
            .buildQueryBuilder().forEntity(LearningGoal.class).get();
    for(int i=0;i<tokenized.length;i++){
         if(i==(tokenized.length-1)){
            Query query = qBuilder.keyword().wildcard().onField("title")
                    .matching(tokenized[i] + "*").createQuery();
                bQuery.add(query, BooleanClause.Occur.MUST);
        }else{
            Term exactTerm = new Term("title", tokenized[i]);
            bQuery.add(new TermQuery(exactTerm), BooleanClause.Occur.MUST);
        }
    }
        for (LearningGoal exGoal : existingGoals) {
        Term omittedTerm = new Term("id", String.valueOf(exGoal.getId()));
        bQuery.add(new TermQuery(omittedTerm), BooleanClause.Occur.MUST_NOT);
    }
    org.hibernate.Query hibQuery = fullTextSession.createFullTextQuery(
            bQuery, LearningGoal.class);
于 2013-03-13T05:52:35.810 に答える
-2

SQLは、他の端末とは異なるワイルドカードを使用します。SQLでは'%'、(代わりに使用する端末で)任意の文字の0個以上の出現箇所を置き換え'*'、アンダースコア'_'は(代わりに使用する端末で)1文字だけを置き換えます'?'。Hibernateはワイルドカード文字を翻訳しません。

したがって、2行目では、次のように置き換える必要がありmatching(searchString + "*")ます

  matching(searchString + "%")
于 2013-03-08T09:38:34.463 に答える