首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Lucene BooleanQuery错误结果

Lucene BooleanQuery错误结果
EN

Stack Overflow用户
提问于 2017-06-20 23:12:14
回答 1查看 345关注 0票数 0

我创建了一个Lucene RAMDirectory来收集来自不同来源的数据,并使它们可以快速搜索。我花了很多时间来理解不同的分析器和索引策略,但在某些情况下,查询结果并不是预期的。

下面是一个演示类:

代码语言:javascript
复制
class LuceneDemo {

    static final String ANIMAL = "animal";
    static final String PERSON = "person";

    private StandardAnalyzer analyzer = new StandardAnalyzer();

    private IndexSearcher searcher;
    private IndexWriter writer;

    LuceneDemo() {
        Directory ramDirectory = new RAMDirectory();
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        try {
            writer = new IndexWriter(ramDirectory, config);

            addDocument(createDocument(PERSON, "DR-(frankenstein)"));
            addDocument(createDocument(ANIMAL, "gray fox"));
            addDocument(createDocument(ANIMAL, "island fox"));

            writer.close();
            IndexReader reader = DirectoryReader.open(ramDirectory);
            searcher = new IndexSearcher(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private Document createDocument(String type, String value) {
        Document document = new Document();
        document.add(new TextField("type", type, Field.Store.YES));
        document.add(new TextField("name", value, Field.Store.YES));
        document.add(new StringField("name", value, Field.Store.YES));
        return document;
    }

    private void addDocument(Document document) {
        try {
            writer.addDocument(document);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    List<String> getDocuments(String type, String value) {
        value = "*" + QueryParser.escape(value) + "*";
        try {
            QueryParser queryParser = new QueryParser("name", analyzer);
            queryParser.setAllowLeadingWildcard(true);
            queryParser.setDefaultOperator(QueryParser.Operator.AND);

            BooleanQuery.Builder query = new BooleanQuery.Builder();
            query.add(new TermQuery(new Term("type", type)), BooleanClause.Occur.MUST);
            query.add(queryParser.parse(value), BooleanClause.Occur.MUST);

            TopDocs docs = searcher.search(query.build(), 10);

            return Arrays.stream(docs.scoreDocs).map(scoreDoc -> {
                try {
                    return searcher.doc(scoreDoc.doc).get("name");
                } catch (IOException e) {
                    return "";
                }
            }).collect(Collectors.toList());
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        }
        return Collections.emptyList();
    }
}

如果我搜索“牛”、“灰狐”或“-(弗兰肯斯坦)”,代码运行得很好。但我对“弗兰肯斯坦博士”没有结果。我不知道我做错了什么。所以任何建议都是欢迎的。

代码语言:javascript
复制
// OK
luceneDemo.getDocuments(LuceneDemo.ANIMAL, "ox").forEach(System.out::println);
luceneDemo.getDocuments(LuceneDemo.ANIMAL, "gray fox").forEach(System.out::println);
luceneDemo.getDocuments(LuceneDemo.PERSON, "-(frankenstein)").forEach(System.out::println);

// NOT OK
luceneDemo.getDocuments(LuceneDemo.PERSON, "DR-(frankenstein)").forEach(System.out::println);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-23 01:41:33

你的文档就是这样被索引的-

  1. doc#1类型:人名:DR名称:frankenstein名称:DR-(Frankenstein)(注意: StringField未被标记,也未转换为小写)
  2. doc#2类型:动物名称:灰色名称:狐狸名称:灰狐狸
  3. doc#3类型:动物名称:岛名:狐名:岛狐

基本上,StringField索引字段与analyzer无关--不进行标记化,并且降低了情况。而阅读器使用的是StandardAnalyzer,降低了所有搜索的范围。因此,搜索"DR-(frankenstein)“会搜索没有匹配的"dr-(frankenstein)”。

要使您的代码使用StandardAnalyzer工作,需要将StringField索引为小写。

代码语言:javascript
复制
document.add(new StringField("name", value.toLowerCase(), Field.Store.YES));
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44664401

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档