如何使用布尔搜索语法进行Java字符串匹配?

14
我正在寻找一个Java/Scala库,可以接受用户查询和文本,并返回是否匹配。
我正在处理信息流,例如Twitter Stream,并且无法使用批处理过程。我需要实时评估每个推文,而不是通过Lucene RAMDisk对其进行索引并稍后查询它。
可以使用ANTLR创建解析器/词法分析器,但这是如此常见的用法,以至于我无法相信之前没有人创建过库。
以下是TextQuery Ruby library的一些示例,完全符合我的需求:
    TextQuery.new("'to be' OR NOT 'to_be'").match?("to be")   # => true

    TextQuery.new("-test").match?("some string of text")      # => true
    TextQuery.new("NOT test").match?("some string of text")   # => true

    TextQuery.new("a AND b").match?("b a")                    # => true
    TextQuery.new("a AND b").match?("a c")                    # => false

    q = TextQuery.new("a AND (b AND NOT (c OR d))")
    q.match?("d a b")                                         # => false
    q.match?("b")                                             # => false
    q.match?("a b cdefg")                                     # => true

    TextQuery.new("a~").match?("adf")                         # => true
    TextQuery.new("~a").match?("dfa")                         # => true
    TextQuery.new("~a~").match?("daf")                        # => true
    TextQuery.new("2~a~1").match?("edaf")                     # => true
    TextQuery.new("2~a~2").match?("edaf")                     # => false

    TextQuery.new("a", :ignorecase => true).match?("A b cD")  # => true

一旦它在Ruby中实现,它就不适合我的平台,而且我不能仅仅为了解决这个问题而使用JRuby:

我找到了一个类似的问题,但无法从中得到答案: 布尔查询/表达式转换为具体语法树

谢谢!


@edgarespina刚刚告诉我有一个名为Parboiled的工具,它似乎与Ruby的Treetop非常相似。也许这是最简单的解决方案。 - arjones
2个回答

3

考虑到您正在进行文本搜索,建议您利用Lucene提供的基础设施。您可以创建一个QueryParser并调用parse方法以获取Query对象。Query的可实例化子类包括:

TermQuery
MultiTermQuery
BooleanQuery
WildcardQuery
PhraseQuery
PrefixQuery
MultiPhraseQuery
FuzzyQuery
TermRangeQuery
NumericRangeQuery
SpanQuery

然后,您可以使用模式匹配来实现应用程序中的匹配含义:

def match_?(tweet: String, query: Query): Boolean = query match {
  case q: TermQuery => tweet.contains(q.getTerm.text)
  case q: BooleanQuery => 
    // return true if all must clauses are satisfied
    // call match_? recursively
  // you need to cover all subclasses above
  case _ => false
}

val q = queryParser.parse(userQuery)
val res = match_?(tweet, q)

这里有一个实现(链接)。它肯定存在错误,但你可以理解它,并且它展示了一个工作的概念证明。它重复使用了默认Lucene QueryParser的语法、文档和语法。


3
Spring表达式语言(SpEL)支持使用正则表达式返回布尔值的matches运算符。有关用法,请参见文档中的this部分。
这还允许您使用逻辑运算符,如andornot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接