7

是否可以使用 Lucene SpanQuery 来查找“红色”“绿色”和“蓝色”这两个词都出现在一个句子中的所有事件?

我的第一个(不完整/不正确)方法是编写一个分析器,将一个特殊的句子标记标记和句子的开头放置在与句子的第一个单词相同的位置,然后查询类似于以下内容的内容:

SpanQuery termsInSentence = new SpanNearQuery(
  SpanQuery[] {
    new SpanTermQuery( new Term (MY_SPECIAL_SENTENCE_TOKEN)),
    new SpanTermQuery( new Term ("red")),
    new SpanTermQuery( new Term ("green")),
    new SpanTermQuery( new Term ("blue")),
  },
  999999999999,
  false
);

SpanQuery nextSentence = new SpanTermQuery( new Term (MY_SPECIAL_SENTENCE_TOKEN));

SpanNotQuery notInNextSentence = new SpanNotQuery(termsInSentence,nextSentence);

当然,问题在于这nextSentence并不是真正的下一个句子,而是任何句子标记,包括句子中termsInSentence匹配的那个。因此这是行不通的。

我的下一个方法是创建将标记放在句子之前的分析器(即第一个单词之前,而不是在与第一个单词相同的位置)。问题是我必须考虑由MY_SPECIAL_SENTENCE_TOKEN. 更重要的是,当我使用幼稚模式拆分句子(例如 split on /\.\s+[A-Z0-9]/)时,这首先会特别糟糕,因为当我搜索USS Enterprise时,我必须考虑所有(错误)句子标记。

那么......我应该如何处理这个?

4

2 回答 2

1

我会将每个句子索引为一个 Lucene 文档,包括一个标记句子来自哪个源文档的字段。根据您的源材料,句子/LuceneDoc 的开销可能是可以接受的。

于 2013-01-24T11:59:11.420 回答
1

实际上,看起来您非常接近解决方案。我认为索引句尾标志是一个好方法。问题是你的句尾标志在你的 中SpanNearQuery,这就是让你失望的原因。您要求它找到一个包含和包含的跨度MY_SPECIAL_SENTENCE_TOKEN。该查询自相矛盾,因此,当然,它不会找到任何匹配项。您真正需要知道的是,这三个术语(“红色”、“绿色”和“蓝色”)出现在不重叠的跨度中MY_SPECIAL_SENTENCE_TOKEN(即句子标记不会出现在这些术语之间)。

此外,在Termctors 中缺少字段名称会是个问题,但是 Lucene应该抛出一个异常来抱怨这一点,所以猜测这不是真正的问题。可能是撰写本文时的 Lucene 版本并没有抱怨 SpanNears 中的不匹配字段,所以也许值得一提。

这似乎对我有用:

SpanQuery termsInSentence = new SpanNearQuery(
    new SpanQuery[] {
        new SpanTermQuery( new Term ("text", "red")),
        new SpanTermQuery( new Term ("text", "green")),
        new SpanTermQuery( new Term ("text", "blue")),
    },
    9999, 
    false
);

SpanQuery nextSentence = new SpanTermQuery( new Term ("text", MY_SPECIAL_SENTENCE_TOKEN));

SpanQuery notInNextSentence = new SpanNotQuery(termsInSentence,nextSentence);

至于在哪里拆分句子,而不是使用天真的正则表达式方法,我会尝试使用java.text.Breakiterator. 它并不完美,但它做得很好。

于 2016-04-01T16:17:35.740 回答