解析Java中的搜索查询

时间:2020-03-05 18:40:12  来源:igfitidea点击:

我一直在尝试寻找一种简单的方法来解析搜索查询并将其转换为数据库的SQL查询。

我发现了两种解决方案:

  • Lucene:强大的基于Java的搜索引擎,包含查询解析器,但是它不是非常可配置的,我可以找到一种方法来轻松地破解/调整它来创建SQL查询。
  • ANTLR:资深文本词法分析器。用于构建从编译器到刮板的所有内容。 ANTLR是高度可配置的,但是从现在开始接触代码的每个人都必须学习一种新的语言...

还有其他想法吗?

解决方案

回答

在很大程度上取决于我们必须解析的查询类型,并在某种程度上取决于数据库中数据的结构。我要假设我们不是要在数据库中进行全文搜索(即整个数据库中的搜索引擎),因为正如大多数信息检索人员会告诉那样,这种方法的性能非常糟糕。倒排索引无疑是最好的方法。

告诉我们更多有关实际问题的信息:用户将输入什么,他们期望输出什么,数据模型是什么样的。设计没有这些信息的搜索解决方案,我们将获得最佳效果。

回答

我们到底在想什么?我已经使用Lucene进行文本搜索,但是它擅长的是建立索引并进行搜索,而不是完全不访问数据库。

我最近建立了一个系统,在其中通过将所有列(用空格分隔)串联到一个字段中,然后将其弹出到Lucene中,然后在单独的列中添加主键,从而在Lucene中建立表的索引。 Lucene进行了所有搜索,并返回了一个主键列表,我用它来提取一组填充的结果并显示给用户。

在我看来,将搜索查询转换为SQL语句似乎有些混乱。

另外,这是一个很好的入门教程,解释了Lucene的基本结构。

回答

我们以为我不是在寻找全文搜索是正确的。
信息看起来像这样的书籍信息架构:
名称:字符串,发布者:字符串,num_pages int,发布日期:date ...

搜索查询属于:

  • 哈利·波特(搜寻任何名字同时有哈利和波特的书籍)
  • 出版商:自然*页数> 100(出版商出版的书籍,以《自然》开头的书籍超过100本)
  • ("新年"或者圣诞节)和礼物(我们得到了图片...)
  • 物理与出版> 1/1/2008(新物理书籍)

回答

我们可以尝试使用类似javacc(Java Compiler Compiler)之类的方法来实现解析器,或者只是通过蛮力手动解析字符串。每次遇到表达式时,都将其表示为对象。然后,我们只需要将表达式树转换为where子句即可。

例如:"哈利·波特"成为

new AndExp(new FieldContainsExp("NAME", "Harry"), new FieldContainsExp("NAME", "Potter")

并且" publisher:Nature *页面> 100"成为

new AndExp(new FieldContainsExp("PUBLISHER", "Nature"), FieldGreaterThan("PAGES", 100))

然后,一旦有了这些,就很容易将它们转换为SQL:

FieldContainsExp.toSQL(StringBuffer sql, Collection<Object> args) {
  sql.append(fieldName);
  sql.append(" like ");
  sql.append("'%?%'");
  args.add(value);
}

AndExp.toSQL(StringBuffer sql, Collection<Object> args) {
    exp1.toSQL(sql, args);
    sql.append(" AND ");
    exp2.toSQL(sql, args);
}

我们可以想象其余的。我们可以根据需要深度嵌套And表达式。

回答

SQL-ORM是一个非常轻量级的Java库,它具有在Java中构造(动态)SQL查询作为对象图的功能。

恕我直言,与通常的String concatentation方法相比,这是一种用于构建动态SQL查询的更好的技术。

免责声明:我对此项目做出了很小的贡献

回答

尝试结合使用ORM工具(如openJPA)和Compass(OSEM框架)。
它会自动索引通过ORM工具完成的更新,并为我们提供Lucene的搜索能力。之后,我们当然可以从数据库中检索对象。
它优于任何基于SQL的搜索解决方案。