Java 索尔:搜索排除更大的短语

Java 索尔:搜索排除更大的短语,java,lucene,solr,Java,Lucene,Solr,F.e.我有3份文件。 1.“狗猫球” 2.“狗狗球猫” 3.“狗、猫、球和大象” 所以。通过查询“狗、猫和球”,我只希望收到前两个文档。 所以我想在结果中只包含我要求的词的主要思想 如有任何建议,我将不胜感激。 谢谢。好的,如果您存储TermVector(在创建字段时,在将文档添加到索引之前,使用TermVector。是的),可以通过覆盖收集器来完成。下面是一个简单的实现(只返回没有分数的文档): 私有静态类MyCollector扩展收集器{ 私有索引阅读器; 专用术语; 私有集=新的Hash

F.e.我有3份文件。
1.“狗猫球”
2.“狗狗球猫”
3.“狗、猫、球和大象”

所以。通过查询“狗、猫和球”,我只希望收到前两个文档。
所以我想在结果中只包含我要求的词的主要思想

如有任何建议,我将不胜感激。

谢谢。

好的,如果您存储TermVector(在创建
字段时,在将
文档添加到索引之前,使用
TermVector。是的
),可以通过覆盖收集器来完成。下面是一个简单的实现(只返回没有分数的文档):

私有静态类MyCollector扩展收集器{
私有索引阅读器;
专用术语;
私有集=新的HashSet();
公共MyCollector(IndexReader ir,国际术语编号){
this.ir=ir;
this.numberOfTerms=numberOfTerms;
}
@凌驾
public void setScorer(Scorer Scorer)抛出IOException{}//在本例中我们不使用Scorer
@凌驾
public void setnextrader(IndexReader阅读器,int docBase){
//忽略
}
@凌驾
公共void collect(int doc)引发IOException{
TermFreqVector=ir.getTermFreqVector(文档,内容\字段);
//CONTENT_field是您正在搜索的字段的名称。。。
如果(向量!=null){
if(vector.getTerms().length==numberOfTerms){
设置、添加(单据);
}
}否则{
set.add(doc);//好吧,假设这不会发生,因为您存储了TermVector。
}
}
@凌驾
公共布尔值AcceptsDocSoutoOrder(){
返回true;
}
公共集getSet(){
返回集;
}
}; 
现在,使用
IndexSearcher\search(查询,收集器)

其思想是:如果要接受文档,您知道文档中应该包含多少术语,因此您只需验证它,并只收集符合此规则的文档。当然,这可能更复杂(在向量中查找特定的术语,在向量中单词的顺序),但这是一般的想法


实际上,如果您存储TermVector,您几乎可以做任何事情,因此只需尝试使用它。

您可以实现一个具有哈希功能的过滤器工厂/标记器对

  • 使用copyfield指令
  • 您需要标记术语
  • 删除stopwords(在您的示例中)
  • 按字母数字顺序对术语排序并保存哈希
  • 展开查询以同时搜索哈希值,如:
  • somestring:“狗、猫和球”和somehash:“狗、猫和球”

    第二个searchquery部分将在查询处理中隐式散列

    这只会导致精确匹配(假阳性概率非常不现实)


    另外,您不需要存储术语向量。这将导致明显较小的索引。

    您的问题是什么?为什么“狗、猫和球”对你不起作用?我不需要smth的文件,只需要狗、猫和球。所以我不需要搜索结果中的第三个案例。你可以做
    +狗+猫+球-大象
    。(或“…和(不是大象)”)但你必须明确排除你不想要的每个词。所以。。。您的意思是-后期处理?@denys:
    Collector\collect(int docID)
    被调用如果文档与搜索()中的查询匹配,您只需使用它筛选结果,因此它是在处理过程中调用的。@amit非常感谢您。我明白你的意思。现在你能告诉我在Solr中在哪里可以使用IndexSearcher吗?我应该将我的更改添加到SolrIndexSearcher?@denys:SolrIndexSearcher扩展了IndexSearcher(org.apache.lucene.search.IndexSearcher),因此您可以更改SolrIndexSearcher,或者使用IndexSearcher的搜索(而不是SolrIndexSearcher中新的重载搜索)。@amit谢谢。每个解决方案都意味着我应该改变解决方案。但我不想这样做:(。。。
    private static class MyCollector extends Collector {
        private IndexReader ir;
        private int numberOfTerms;
        private Set<Integer> set = new HashSet<Integer>();
    
        public MyCollector(IndexReader ir,int numberOfTerms) {
            this.ir = ir;
            this.numberOfTerms = numberOfTerms;
    
        }
    
        @Override
        public void setScorer(Scorer scorer) throws IOException {   } //we do not use a scorer in this example
    
        @Override
        public void setNextReader(IndexReader reader, int docBase) {
            //ignore
        }
    
        @Override
        public void collect(int doc) throws IOException {
            TermFreqVector vector = ir.getTermFreqVector(doc, CONTENT_FIELD);
                        //CONTENT_FILED is the name of the field you are searching in...
            if (vector != null) {
                if (vector.getTerms().length == numberOfTerms) {
                    set.add(doc);
                }
            } else {
                set.add(doc); //well, assume it doesn't happen, because you stored your TermVectors.
            }
    
        }
    
        @Override
        public boolean acceptsDocsOutOfOrder() {
            return true;
        }
        public Set<Integer> getSet() { 
            return set;
        }
    };