【问题标题】:Lucene search on multiple fields but match on anyLucene 搜索多个字段,但匹配任何字段
【发布时间】:2014-03-21 15:00:17
【问题描述】:

我目前正在尝试创建一个查询,我可以在其中搜索 4 个字段,但返回与任何字段匹配的文档。

谁能告诉我如何设置它。我已经尝试过 BooleanQuery 和 MultiFieldQueryParser,但没有任何结果。

    BooleanQuery booleanQuery = new BooleanQuery();
    Query query1 = new TermQuery(new Term("field1", text1));
    Query query2 = new TermQuery(new Term("field2", text2));
    Query query3 = new TermQuery(new Term("field3", text3));
    Query query4 = new TermQuery(new Term("field4", text4));
    booleanQuery.add(query1, Occur.SHOULD);
    booleanQuery.add(query2, Occur.SHOULD);
    booleanQuery.add(query3, Occur.SHOULD);
    booleanQuery.add(query4, Occur.SHOULD);


    MultiFieldQueryParser multiQueryParser = new MultiFieldQueryParser(Version.LUCENE_44, 
            new String[] {"field1", "field2", "field3", "field4"}, analyzer);

    multiQueryParser.setDefaultOperator(Operator.OR);

我使用 multiQueryParser 获得结果,其中运算符设置为 AND,但是我没有得到任何结果。我认为只有当 2 个字段匹配时才会返回结果。

有人可以提出问题吗?

谢谢

此外,我正在寻找部分匹配或完全匹配。

完整代码:

公开课演示{

IndexWriter indexWriter = null;

public boolean openIndex() {
    try {
        Directory dir = FSDirectory.open(new File(indexerPath));
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_44);
        IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_44, analyzer);
        indexWriter = new IndexWriter(dir, iwc);
        isIndexOpen = true;
        return true;
    } catch (Exception e) {
        return false;
    }
}

public void finish() {
    try {
        indexWriter.close();
        isIndexOpen = false;
    } catch (IOException e) {
    }
}

@Override
public void addDoc(MyObject obj) {
    Document doc = new Document();
    doc.add(new TextField("field1", obj.getField1(), Field.Store.YES));
    doc.add(new TextField("field2", obj.getField2(),, Field.Store.YES));
    doc.add(new TextField("field3", obj.getField3(),, Field.Store.YES));
    doc.add(new TextField("field4", obj.getField4(),, Field.Store.YES));

    try {
        indexWriter.addDocument(doc);
    } catch (IOException e) {

    }
}

@Override
public void getResults(String text) throws ParseException, IOException {
    Directory dir = FSDirectory.open(new File(indexerPath));
    IndexReader reader = DirectoryReader.open(dir);
    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_44);

    MultiFieldQueryParser multiQueryParser = new MultiFieldQueryParser(Version.LUCENE_44, 
            new String[] {"field1", "field2", "field3", "field4"}, analyzer);

    multiQueryParser.setDefaultOperator(Operator.OR);
    Query query = multiQueryParser.parse(text);
    searcher.search(query, collector);
    hits = collector.topDocs().scoreDocs;

    for (int i = 0; i < hits.length; ++i) {
        int docId = hits[i].doc;
        Document d = searcher.doc(docId);
        Log.info("\f1: "+d.get("field1") + " f2: " + d.get("field2") + 
                " f3: "+d.get("field3") + " f4: "+ d.get("field3"));
    }

    return results;
}

}

【问题讨论】:

  • 您的两个查询似乎都可以。您能否提供一个带有 IndexWriter 的独立示例,显示您如何添加文档以及您在搜索什么(我指的是 text1,... text4)?注意:如果你想要部分匹配,你需要使用通配符,例如text1*.
  • 抱歉 text1-4 是同一个词。文档 keyDoc = new Document(); doc.add(new TextField("field1", str1, Field.Store.YES)); doc.add(new TextField("field2", str2.getIntexDealName(), Field.Store.YES)); doc.add(new TextField("field3", str3.getBbDealNameShort(), Field.Store.YES)); doc.add(new TextField("field4", str4, Field.Store.YES));
  • IndexWriter 是使用 IndexWriterConfig 和 StandardAnalyzer 创建的。基本上,当我使用 multiFieldParser 时,我似乎只在 2 个字段匹配时才得到结果。当匹配一个或多个字段时,我想返回匹配项。
  • 可能是 lucene 没有返回小查询的命中。例如,如果我搜索一个字段的全文,我会得到回击,但如果我从搜索中删除一个字符,我不会得到任何回击。即使我输入了 1 个或 2 个字符,如何返回匹配项?
  • 您需要在问题中解释所有这些问题(“如果我删除一个字符”)。最好在代码中解释:-)

标签: java lucene


【解决方案1】:

自包含示例 是指编译并不依赖外部资源来运行/演示问题的代码。你的代码没有。

这是您的代码的修改版本,它可以工作并演示部分匹配。

public class Demo {

    static Directory dir;

    IndexWriter indexWriter;

    public boolean openIndex() {
        try {
            dir = new RAMDirectory();
            Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_44);
            IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_44, analyzer);
            indexWriter = new IndexWriter(dir, iwc);

            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public void finish() {
        try {
            indexWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void addDoc() {
        Document doc = new Document();
        doc.add(new TextField("field1", "val1", Field.Store.YES));
        doc.add(new TextField("field2", "val2", Field.Store.YES));
        doc.add(new TextField("field3", "val3", Field.Store.YES));
        doc.add(new TextField("field4", "val4", Field.Store.YES));

        try {
            indexWriter.addDocument(doc);
            indexWriter.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void printResults(Query query) throws IOException {
        IndexReader reader = DirectoryReader.open(dir);
        IndexSearcher searcher = new IndexSearcher(reader);
        TopDocs result = searcher.search(query, 5);
        System.out.println("# of results:" + result.totalHits);
        for (ScoreDoc doc : result.scoreDocs) {
            System.out.println(doc);
        }

        reader.close();
    }

    public static void main(String[] args) throws IOException, ParseException {
        Demo demo = new Demo();
        demo.openIndex();
        demo.addDoc();
        demo.finish();


        BooleanQuery booleanQuery = new BooleanQuery();
        Query query1 = new TermQuery(new Term("field1", "val1"));
        Query query2 = new TermQuery(new Term("field2", "val2"));
        Query query3 = new TermQuery(new Term("field3", "val3"));
        Query query4 = new TermQuery(new Term("field4", "val4"));
        booleanQuery.add(query1, BooleanClause.Occur.SHOULD);
        booleanQuery.add(query2, BooleanClause.Occur.SHOULD);
        booleanQuery.add(query3, BooleanClause.Occur.SHOULD);
        booleanQuery.add(query4, BooleanClause.Occur.SHOULD);
        printResults(booleanQuery);

        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_44);
        MultiFieldQueryParser multiQueryParser = new MultiFieldQueryParser(Version.LUCENE_44,
                    new String[] {"field1", "field2", "field3", "field4"}, analyzer);
        multiQueryParser.setDefaultOperator(QueryParser.Operator.OR);

        Query mfQuery = multiQueryParser.parse("field1:val1 field2:val2 field3:val3 field4:val4");
        printResults(mfQuery);

        Query mfQuery2 = multiQueryParser.parse("field1:val* field2:x field3:y field4:z");
        printResults(mfQuery2);

    }
}

【讨论】:

  • 谢谢 我没有意识到对于部分结果我需要 *,我很困惑,因为没有 * 我仍然得到一些部分查询匹配但并非总是如此。这就是让我感到困惑的地方。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多