【问题标题】:Lucene Queryparser with multiple fields具有多个字段的 Lucene Queryparser
【发布时间】:2015-12-15 08:09:24
【问题描述】:

我使用 Lucene 5.3 并尝试使用 queryparser-syntax 搜索多个字段。我在 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) OR course_code :(3436NRX) 结果为 0。 搜索中的错误在哪里?

【问题讨论】:

    标签: lucene query-parser


    【解决方案1】:

    我运行了这个并尝试了title:(part) OR course_code:(3436NRX),我得到了 2 个结果,完全符合我的预期。也许您的意思是您期待与 course_code 匹配的第三个结果,但没有得到它。如果您的意思是您实际上通过该查询获得了 个结果,我不确定问题出在哪里。

    那么,为什么你不能在 course_code 上找到匹配项?

    就像 lucene 的情况一样,您的分析器不匹配。您的 queryparser 正在使用 StandardAnalyzer,但 course_code 是 StringField,因此根本没有对其进行分析。 StandardAnalyzer 包含一个过滤器将所有内容都小写,因此最终结果是您有一个包含3436NRX 的字段和一个针对course_code:3436nrx 的查询。

    可能的解决方案是:

    • 使用TermQuery 代替StringFields 的查询解析器
    • 在将 course_code 传递给 lucene 之前自己将其小写
    • 将 course_code 设为 TextField

    等等

    【讨论】:

    • 非常感谢,带有“StringField”的点解决了这个问题。我将改用 TextField,一切都按预期工作。
    猜你喜欢
    • 2011-08-31
    • 2011-01-01
    • 2012-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2014-06-01
    相关资源
    最近更新 更多