2015-03-13 86 views
4

我想使用Lucene(版本4.10)来处理数百万条新闻数据。我对Lucene来说很新,所以我想了解它是如何工作的。在每个lucene文档中,我都会存储一篇新闻文章。每篇文章当然都有其内容(字段被称为“TextContent”)。为什么我的短语查询给我这么小的结果?

我创建这样的领域(涉及this计算器问题):

/* Indexed, tokenized, stored. */ 
public static final FieldType TYPE_STORED = new FieldType(); 

static { 
    TYPE_STORED.setIndexed(true); 
    TYPE_STORED.setTokenized(true); 
    TYPE_STORED.setStored(true); 
    TYPE_STORED.setStoreTermVectors(true); 
    TYPE_STORED.setStoreTermVectorPositions(true); 
    TYPE_STORED.freeze(); 
} 

doc.add(new Field("TextContent", oneArticle.getTextContent(), TYPE_STORED)); 

我不喜欢这样,因为我想有保存以及文本内容项向量(用于创建短语查询,所以我可以轻松地检索一篇新闻文章的术语矢量,并用其内容查找其他相关文章)。

我现在要搜索一个或多个单词(与布尔条款合并Occur.SHOULD或必须)

我的代码看起来像这样(的话简直是包含所有条件来搜索列表)

IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(PATH_TO_INDEX))); 
IndexSearcher searcher = new IndexSearcher(reader); 

BooleanQuery booleanQuery = new BooleanQuery(); 

//words is simply a List<String> containing all terms to search for 
for (String word : words) { 
    PhraseQuery query = new PhraseQuery(); 
    query.add(new Term("TextContent", word)); 
    booleanQuery.add(query, BooleanClause.Occur.SHOULD); 
} 

//collects the results via scoring them using a Similarity Function 
TopScoreDocCollector collector = TopScoreDocCollector.create(reader.numDocs(), true); 
searcher.search(booleanQuery, collector); 
ScoreDoc[] hits = collector.topDocs().scoreDocs; 

System.out.println(hits.length); 

for(int i = 0; i < 10; i++){ 
    int id = hits[i].doc; 
    Document d = searcher.doc(id); 

    System.out.println(d.get("TextContent")); 
} 

我不时得到结果,但还不够,只有非常流行的搜索条件(例如,“足球”作为搜索条件为我提供15000篇文章,同时有数百万篇新闻文章)。

当我搜索我的textContent字段包含的不太流行的术语时,我得到0个结果。比如我与的TextContent启动文件:

“桑尼·威廉姆斯将与前所有黑人队长团聚塔纳 了Umaga [..] 29岁的双橄榄球国际[...]。 “

如果我知道在我的列表单词中只添加单词”橄榄球“,我会得到4125个结果,前10名还有我刚才引用的文章。如果我只是添加单词“威廉姆斯”(作为这个橄榄球球员的名字 - 请参阅上面的报价),我得到0个结果。

我不明白这种行为。我在猜测它必须处理如何在我的Lucene索引中创建“TextContent”字段这一事实。正在进行的谷歌研究将我引向了其他一些计算器问题(例如herehere)。与我的问题不同的是,我不时得到结果,但仅限于非常流行的术语。

你能告诉我我做错了什么吗?你能告诉我如何改变我的TextContent Field/FieldType来提供更好的结果吗?或者,我应该如何改变我的疑问?

非常感谢每一个答案,并认为你与我分享。

更新:全新知识ARRIVED

this计算器的问题,我得到了主意,试图“威廉姆斯”,而不是“威廉姆斯”(全部小写)。从其中一个答案的报价是:

为什么你没有得到你的文件后面的原因是,虽然 索引你使用StandardAnalyzer,令牌转换为小写 并删除停用词。

这工作。如果我写下所有的小写,我会得到结果。我还检查了我的索引与卢克,发现我的术语向量中的所有术语都转换为小写。我现在将在这里留下这个更新并给出更多潜在答案的空间(可能还是有些错误/需要改进才能获得更好的结果)。如果没有答案传入,我将在以后发布这个答案。

回答

0

听起来像你找到了问题的原因。处理这个问题的另一个选项是,使用QueryParser来构建查询时,可以应用相同的分析器。如果你是一个用户得到一个词组输入,然后以某种方式获取变量words解析它,那么这可能是一个更容易和更强大的处理它的方式:

QueryParser parser = new QueryParser("TextContent", new StandardAnalyzer()); 
//if you are actually looking for a phrase 
Query queryPhrase = parser.parse("\"" + inputPhrase + "\""); 
//if instead you want independant term queries 
Query queryTerms = parser.parse(inputPhrase); 

另一个请注意,构建仅有一个词的PhraseQuery没有多大意义。我不知道以下哪些你正在寻找有:

for (String word : words) { 
    TermQuery query = new TermQuery(new Term("TextContent", word)); 
    booleanQuery.add(query, BooleanClause.Occur.SHOULD); 
} 

或者:

PhraseQuery query = new PhraseQuery(); 
for (String word : words) { 
    query.add(new Term("TextContent", word)); 
} 
booleanQuery.add(query, BooleanClause.Occur.SHOULD); 
相关问题