从Lucene查询中获取匹配的术语

从Lucene查询中获取匹配的术语,lucene,Lucene,给定一个Lucene搜索查询,如:+(字母:a字母:B字母:C)+(样式:大写),我如何判断这三个字母中的哪一个与任何给定文档实际匹配?我不在乎他们在哪里比赛,也不在乎他们比赛多少次,我只需要知道他们是否匹配 其目的是进行初始查询(“A B C”),删除成功匹配的术语(A和B),然后对其余的术语(C)进行进一步处理。您可以对每个术语使用A,并根据它们的名称快速检查每个文档id。尽管示例是C#,但Lucene API非常相似(一些大写/小写的差异)。我认为翻译成java并不难 这就是用法 List

给定一个Lucene搜索查询,如:
+(字母:a字母:B字母:C)+(样式:大写)
,我如何判断这三个字母中的哪一个与任何给定文档实际匹配?我不在乎他们在哪里比赛,也不在乎他们比赛多少次,我只需要知道他们是否匹配


其目的是进行初始查询(“A B C”),删除成功匹配的术语(A和B),然后对其余的术语(C)进行进一步处理。

您可以对每个术语使用A,并根据它们的名称快速检查每个文档id。

尽管示例是C#,但Lucene API非常相似(一些大写/小写的差异)。我认为翻译成java并不难

这就是用法

List<Term> terms = new List<Term>();    //will be filled with non-matched terms
List<Term> hitTerms = new List<Term>(); //will be filled with matched terms
GetHitTerms(query, searcher,docId, hitTerms,terms);
List terms=new List();//将用不匹配的术语填充
List hitTerms=new List();//将用匹配的术语填充
GetHitTerms(查询、搜索、文档ID、hitTerms、术语);
这里是方法

void GetHitTerms(查询查询、索引搜索器搜索器、int docId、列表hitTerms、列表REST)
{
如果(查询为TermQuery)
{
if(searcher.Explain(query,docId).IsMatch()==true)
Add((查询为TermQuery.GetTerm());
其他的
Add((作为TermQuery.GetTerm()查询);
返回;
}
if(查询为布尔查询)
{
BooleanClause[]子句=(作为BooleanQuery进行查询).getClaires();
if(子句==null)返回;
foreach(条款中的布尔条款bc)
{
GetHitTerms(bc.GetQuery(),searcher,docId,hitTerms,rest);
}
返回;
}
if(查询为多项查询)
{
如果(!(查询为FuzzyQuery))//FuzzQuery不支持SetRewriteMethod
(查询为MultiTermQuery).SetRewriteMethod(MultiTermQuery.SCORING\u BOOLEAN\u query\u REWRITE);
GetHitTerms(query.Rewrite(searcher.GetIndexReader()),searcher,docId,hitTerms,rest);
}
}

正如@L.B给出的答案,下面是JAVA的转换代码,它对我有用:

void GetHitTerms(Query query,IndexSearcher searcher,int docId,List<Term> hitTerms,List<Term>rest) throws IOException
    {
        if(query instanceof TermQuery )
        {
            if (searcher.explain(query, docId).isMatch())
                hitTerms.add(((TermQuery) query).getTerm());
            else
                rest.add(((TermQuery) query).getTerm());
            return;
        }

            if(query instanceof BooleanQuery )
            {
                for (BooleanClause clause : (BooleanQuery)query) {
                    GetHitTerms(clause.getQuery(), searcher, docId,hitTerms,rest);
            }
            return;
        }

        if (query instanceof MultiTermQuery)
        {
            if (!(query instanceof FuzzyQuery)) //FuzzQuery doesn't support SetRewriteMethod
                ((MultiTermQuery)query).setRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);

            GetHitTerms(query.rewrite(searcher.getIndexReader()), searcher, docId,hitTerms,rest);
        }
    }
void GetHitTerms(查询查询、索引搜索器搜索器、int docId、列表hitTerms、列表REST)引发IOException
{
if(查询实例of TermQuery)
{
if(searcher.explain(query,docId).isMatch())
add(((TermQuery)query.getTerm());
其他的
add(((TermQuery)query.getTerm());
返回;
}
if(布尔查询的查询实例)
{
for(BooleanClause子句:(BooleanQuery)查询){
GetHitTerms(子句.getQuery()、搜索器、文档ID、hitTerms、rest);
}
返回;
}
if(多项查询的查询实例)
{
如果(!(FuzzyQuery的查询实例))//FuzzQuery不支持SetRewriteMethod
(MultiTermQuery)query.setRewriteMethod(MultiTermQuery.SCORING\u BOOLEAN\u query\u REWRITE);
GetHitTerms(query.rewrite(searcher.getIndexReader()),searcher,docId,hitTerms,rest);
}
}

我基本上使用了与相同的方法,但在最新的Lucene版本7.4.0中对其进行了更新。注意:FuzzyQuery现在支持.setRewriteMethod(这就是我删除if的原因)

我还包括对BoostQuerys的处理,并将Lucene找到的单词保存在哈希集中,以避免重复,而不是术语

private void saveHitWordInList(Query query, IndexSearcher indexSearcher,
    int docId, HashSet<String> hitWords) throws IOException {
  if (query instanceof TermQuery)
    if (indexSearcher.explain(query, docId).isMatch())
      hitWords.add(((TermQuery) query).getTerm().toString().split(":")[1]);
  if (query instanceof BooleanQuery) {
    for (BooleanClause clause : (BooleanQuery) query) {
      saveHitWordInList(clause.getQuery(), indexSearcher, docId, hitWords);
    }
  }

  if (query instanceof MultiTermQuery) {
    ((MultiTermQuery) query)
        .setRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_REWRITE);
    saveHitWordInList(query.rewrite(indexSearcher.getIndexReader()),
        indexSearcher, docId, hitWords);
  }

  if (query instanceof BoostQuery)
    saveHitWordInList(((BoostQuery) query).getQuery(), indexSearcher, docId,
        hitWords);
}
private void saveHitWordInList(查询查询、索引搜索器、索引搜索器、,
int docId,HashSet hitWords)引发IOException{
if(查询实例of TermQuery)
if(indexSearcher.explain(查询,docId.isMatch())
hitWords.add(((TermQuery)query.getTerm().toString().split(“:”[1]);
if(布尔查询的查询实例){
for(BooleanClause子句:(BooleanQuery)查询){
saveHitWordInList(子句.getQuery(),索引搜索器,文档ID,hitWords);
}
}
if(多项查询的查询实例){
((多项查询)查询)
.setRewriteMethod(MultiTermQuery.SCORING\u BOOLEAN\u REWRITE);
saveHitWordInList(query.rewrite(indexSearcher.getIndexReader()),
索引搜索器、文档ID、hitWords);
}
if(BoostQuery的查询实例)
saveHitWordInList(((BoostQuery)query).getQuery(),indexSearcher,docId,
(单字),;
}

这是Lucene.NET 4.8的简化版和非递归版。
未经验证,但这在Lucene.NET 3.x上也应该有效

IEnumerable GetHitTermsForDoc(查询查询、索引搜索器搜索器、int docId)
{
//将查询重写为ExtractTerms所需的更简单的内部形式
var simplifiedQuery=query.Rewrite(searcher.IndexReader);
HashSet queryTerms=新HashSet();
simplifiedQuery.ExtractTerms(queryTerms);
List hitTerms=新列表();
foreach(QueryTerm中的变量项)
{
var termQuery=新termQuery(术语);
var解释=searcher.Explain(termQuery,docId);
如果(解释.IsMatch)
{
添加(术语);
}
}
退货条件;
}

这可能是因为我对Lucene不熟悉,但我不知道该如何使用它。我现在没有一个过滤器——只有一个查询,查询条件每次都会改变——它可以是“a B”,也可以是“a F B Q”。我可以从查询中创建一个QueryFilter,但这似乎是多余的(尽管可能是必要的).I也没有用于过滤器的GetDocIdSet()函数的indexReader,只有一个IndexSearcher().你能提供一个使用示例吗?事实上,我刚刚意识到如何获得IndexReader-我已经在代码的其他地方使用了它。不过,其余的注释仍然适用。这正是我所需要的,因为我已经在使用Lucene.net,我甚至不需要翻译它。谢谢!(我意识到我可能应该使用lucene.net标签,但我认为这是一个关于系统的一般性问题,而不是一个与.net风格有关的问题,因为它们的工作原理是一样的)。我不再从事这项工作,所以我无法测试它,但这个定义