elasticsearch,Lucene,elasticsearch" /> elasticsearch,Lucene,elasticsearch" />

Lucene SpanNotQuery提供意外结果(忽略排除)

Lucene SpanNotQuery提供意外结果(忽略排除),lucene,elasticsearch,Lucene,elasticsearch,elasticsearch中的SpanNotQuery有一些问题。查询的排除部分似乎已被忽略 为了重现问题,我创建了一组文档: 菲茨科彭酒店 菲茨洛本酒店 哈里科彭 哈里洛本 哈里菲茨 科彭·洛本 对harrie的spanterm查询将导致(3、4、5) kopen的spanTerm查询将导致(1、3、6) 现在,我想在一个SpanNotQuery中组合这个函数,其中include为“harrie”,exclude为“kopen” 我希望结果是(4,5),但它是(3,4,5) 我们必须使用spa

elasticsearch中的SpanNotQuery有一些问题。查询的排除部分似乎已被忽略

为了重现问题,我创建了一组文档:

  • 菲茨科彭酒店
  • 菲茨洛本酒店
  • 哈里科彭
  • 哈里洛本
  • 哈里菲茨
  • 科彭·洛本
  • 对harrie的spanterm查询将导致(3、4、5)

    kopen的spanTerm查询将导致(1、3、6)

    现在,我想在一个SpanNotQuery中组合这个函数,其中include为“harrie”,exclude为“kopen”

    我希望结果是(4,5),但它是(3,4,5)

    我们必须使用span查询,这只是我们遇到的问题的一小部分

    我创建了一个只有Lucene的单元测试来显示我们的问题

    公共类LuceNet{
    @试验
    public void test()引发异常{
    RAMDirectory ram=新的RAMDirectory();
    createAndFillIndex(ram);
    DirectoryReader=DirectoryReader.open(ram);
    IndexSearcher search=新的IndexSearcher(directoryReader);
    SpanQuery include=新的SpanTermQuery(新术语(“虚拟”、“哈里”));
    SpanQuery exclude=新的SpanTermQuery(新术语(“伪”、“kopen”));
    查询spanNot=新的SpanNotQuery(包括、排除);
    TopDocs search=searcher.search(spanNot,100);
    for(ScoreDoc ScoreDoc:search.scoreDocs){
    文档结果=searcher.doc(scoreDoc.doc);
    字符串dummy=result.get(“dummy”);
    System.out.println(scoreDoc.doc+“:”+虚拟);
    }
    }
    私有void createAndFillIndex(RAMDirectory ram)引发IOException{
    IndexWriterConfig conf=newindexwriterconfig(Version.LUCENE_47,new SimpleAnalyzer(Version.LUCENE_47));
    IndexWriter writer=新的IndexWriter(ram,配置);
    添加(writer,“nul”);//0
    添加(写入器,“fiets kopen”);//1
    添加(作者,“菲茨·洛本”);//2
    添加(作者,“harrie kopen”);//3
    添加(作家,“哈里洛本”);//4
    添加(作者,“harrie fiets”);//5
    添加(编写器,“kopen lopen”);//6
    writer.close();
    }
    私有void add(IndexWriter writer,字符串值)引发IOException{
    单据单据=新单据();
    IndexableField f=新文本字段(“虚拟”,值,字段。存储。是);
    添加文件(f);
    writer.addDocument(doc);
    }
    }
    
    有人知道我们做错了什么吗


    谢谢

    文档在这里给出了一个提示。它匹配:

    包含中的跨距与排除中的跨距没有重叠

    我们处理的是跨度,而不是整个文档。不过,简单术语查询的匹配范围只是单个术语。在您的示例中的三个匹配文档中,匹配的跨度都是
    harrie
    ,这与任何文档中的术语
    kopen
    都没有任何重叠

    看一个例子来说明它是如何工作的可能会更有帮助。您应该能够将以下片段复制粘贴到您的示例中(顺便说一句,感谢您的支持!)。让我们试试这个查询:

    SpanQuery include=new SpanTermQuery(新术语(“dummy”、“harrie”));
    SpanQuery exclude=新的SpanTermQuery(新术语(“伪”、“kopen”));
    SpanQuery matchterm=新SpanTermQuery(新术语(“伪”、“匹配”));
    SpanQuery[]子句={include,matchterm};
    SpanQuery nearQuery=新的span查询(子句,2,true);
    Query spanNot=新的SpanNotQuery(nearQuery,exclude);
    
    根据这些文件:

    add(writer,“harrie kopen match”)//1.
    添加(作者,“harrie match kopen”)//2.
    添加(作者,“harrie other stuff match kopen”)//3.
    
    你应该看到2支安打

    • 文档1:将
      nearQuery
      与span:“harrie kopen match”匹配。它包含“kopen”(即与span匹配的
      exclude
      重叠),因此
      SpanNotQuery

    • 文档2:将
      nearQuery
      与span:“harrie match”匹配。文档包含“kopen”,但不在匹配的范围内,因此文档保持匹配

    • 文档3:将
      nearQuery
      与span“marrieotherstuff match”匹配。同样,文档包含“kopen”,但不在匹配的范围内,因此它可以通过

    如果您希望否定覆盖整个文档,而不仅仅是匹配的范围,请改用
    BooleanQuery

    SpanQuery include=new SpanTermQuery(新术语(“dummy”、“harrie”));
    SpanQuery exclude=新的SpanTermQuery(新术语(“伪”、“kopen”));
    Query Query=new BooleanQuery();
    add(新的BooleanClause(include,BooleanClause.occure.MUST))
    添加(新的BooleanClause(排除,BooleanClause.occurrent.NOT))