Lucene 4.2 StringField

Я новичок в Lucene. У меня есть два документа, и я хотел бы иметь точное совпадение для поля документа под названием "ключевое слово" (поле может встречаться в документе несколько раз).

Первый документ содержит ключевое словоАннотация это круто, Второй документ содержит ключевое словоАннотация тоже классная, Как мне построить запрос так, чтобы при поиске был найден только первый документ?Аннотация это круто "?

Я читаю кое-что оСтрингфилд» и что это не токенизировано. Если я поменяюключевое слово" поле от "Текстовое поле" к "Стрингфилд» в методеaddDoc» тогда ничего не будет найдено.

Вот мой код:

private IndexWriter writer;

public void lucene() throws IOException, ParseException {
    // Build the index
    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_42);
    Directory index = new RAMDirectory();
    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_42,
            analyzer);
    this.writer = new IndexWriter(index, config);

    // Add documents to the index
    addDoc("Spring", new String[] { "Java", "JSP",
            "Annotation is cool" });
    addDoc("Java", new String[] { "Oracle", "Annotation is cool too" });

    writer.close();

    // Search the index
    IndexReader reader = DirectoryReader.open(index);
    IndexSearcher searcher = new IndexSearcher(reader);

    BooleanQuery qry = new BooleanQuery();

    qry.add(new TermQuery(new Term("keyword", "\"Annotation is cool\"")), BooleanClause.Occur.MUST);

    System.out.println(qry.toString());

    Query q = new QueryParser(Version.LUCENE_42, "title", analyzer).parse(qry.toString());

    int hitsPerPage = 10;
    TopScoreDocCollector collector = TopScoreDocCollector.create(
            hitsPerPage, true);

    searcher.search(q, collector);

    ScoreDoc[] hits = collector.topDocs().scoreDocs;

    for (int i = 0; i < hits.length; ++i) {
        int docId = hits[i].doc;
        Document doc = searcher.doc(docId);
        System.out.println((i + 1) + ". \t" + doc.get("title"));
    }

    reader.close();
}

private void addDoc(String title, String[] keywords) throws IOException {
    // Create new document
    Document doc = new Document();

    // Add title
    doc.add(new TextField("title", title, Field.Store.YES));

    // Add keywords
    for (int i = 0; i < keywords.length; i++) {
        doc.add(new TextField("keyword", keywords[i], Field.Store.YES));
    }

    // Add document to index
    this.writer.addDocument(doc);
}

Ответы на вопрос(1)

Решение Вопроса

Ваша проблема не в том, как вы индексируете поле. Строковое поле - это правильный способ индексировать весь ввод как один токен. Проблема в том, как вы ищете. Я действительно нене знаю, чего вы намерены достичь с помощью этой логики.

BooleanQuery qry = new BooleanQuery();
qry.add(new TermQuery(new Term("keyword", "\"Annotation is cool\"")), BooleanClause.Occur.MUST);
//Great! You have a termQuery added to the parent BooleanQuery which should find your keyword just fine!

Query q = new QueryParser(Version.LUCENE_42, "title", analyzer).parse(qry.toString());
//Now all bets are off.

Query.toString() это удобный метод отладки, но небезопасно предполагать, что выполнение выходного текстового запроса через QueryParser сгенерирует тот же запрос. Стандартный парсер запросов действительно неу него есть много возможностей выразить несколько слов одним словом. Я полагаю, что строковая версия этого будет выглядеть следующим образом:

keyword:"Annotation is cool"

Который будет интерпретироваться как PhraseQuery. PhraseQuery будет искать три последовательных условия,Аннотация,является, а такжепрохладноНо, как вы проиндексировали это, у вас есть один термин "Аннотация это круто ".

Решение неникогда не использовать логику, как

 Query nuttyQuery = queryParser.parse(perfectlyGoodQuery.toString());
 searcher.search(nuttyQuery);

Вместо этого просто выполните поиск с помощью BooleanQuery, который вы уже создали.

 searcher.search(perfectlyGoodQuery);
 femtoRgon06 июн. 2013 г., 18:38
Похоже, вы заключаете его в кавычки только при построении запроса, а не при индексации, поэтому удалите кавычки из запроса Term.
 devchzh06 июн. 2013 г., 18:42
Да, теперь это работает! Большое спасибо за Вашу помощь!
 devchzh06 июн. 2013 г., 18:26
Большое спасибо за Вашу помощь. Если я раскомментирую строку с "Запрос q ... » и измените параметр "q" к "QRY» в "searcher.search (...)»ничего не найдено. Я также изменил на StringField, но безуспешно.

Ваш ответ на вопрос