Lucene Queryparser с несколькими полями

Я использую Lucene 5.3 и пытаюсь искать по нескольким полям, используя синтаксис queryparser. Я нашел в Учебниках Lucene короткий пример и изменил его до Версии 5.3 и поиска по этим полям.

package lucenewriterexample;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;

import java.io.IOException;

public class LuceneWriterExample {


    public static void main(String[] args) throws IOException, ParseException {
        StandardAnalyzer analyzer = new StandardAnalyzer();
        Directory index = new RAMDirectory();
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        try (IndexWriter writer = new IndexWriter(index, config)) {
            addDoc(writer, "Day first : Lucence Introduction test.", "3436NRX");
            addDoc(writer, "Day second , part one : Lucence Projects.", "3437RJ1");
            addDoc(writer, "Day second , part two: Lucence Uses testing rr.", "3437RJ2");
            addDoc(writer, "Day third : Lucence Demos.", "34338KRX");
        }

        String querystr = "title:(part) AND course_code:(3437RJ1)";
        Query q = new QueryParser("title", analyzer).parse(querystr);

        // 3. searching
        int hitsPerPage = 10;
        IndexReader reader = DirectoryReader.open(index);
        IndexSearcher searcher = new IndexSearcher(reader);
        TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage);
        searcher.search(q, collector);
        ScoreDoc[] hits = collector.topDocs().scoreDocs;

        // 4. display results
        System.out.println("Query string: " + querystr );
        System.out.println("Found " + hits.length + " hits.");        
        for (int i = 0; i < hits.length; ++i) {
            int docId = hits[i].doc;
            Document d = searcher.doc(docId);
            System.out.println((i + 1) + ". " + d.get("course_code") + "\t" + d.get("title"));
        }

        // Finally , close reader
    }

    private static void addDoc(IndexWriter w, String title, String courseCode) throws IOException {
        Document doc = new Document();
        doc.add(new TextField  ("title",       title,      Field.Store.YES));
        doc.add(new StringField("course_code", courseCode, Field.Store.YES));
        w.addDocument(doc);
    }

Парсер запросов работает для "title: part", тогда я получаю все документы, содержащие "part", но если я использую "title:(part) AND course_code:(3437RJ1)" или "title: (part) ИЛИ course_code:(3436NRX) результат равен 0. Где ошибка в поиске?

1 ответ

Решение

Я запустил это и попытался title:(part) OR course_code:(3436NRX)и я получаю 2 результата, как я и ожидал. Возможно, вы имели в виду, что ожидали третий результат, соответствующий коду course_code, но не получили его. Если вы действительно имели в виду, что вы получили нулевой результат с этим запросом, я не уверен, в чем проблема.

Итак, почему вы не можете найти совпадение по коду course_code?

Как это часто бывает в случае с люценом, у вас не совпадают анализаторы. Ваш запроспарсер использует StandardAnalyzer, но код_курса является StringFieldи поэтому он вообще не анализируется. StandardAnalyzer включает в себя фильтр для строчных букв, так что в итоге у вас есть поле, которое имеет 3436NRXи запрос для course_code:3436nrx,

Возможные решения будут:

  • Использовать TermQuery вместо парсера запросов для вашего StringFields
  • Строковый код вашего_курса перед передачей в lucene
  • Сделать код курса TextField

и т.п.

Другие вопросы по тегам