在启动我想要运行的完整XQuery之前,如何验证嵌入较大XQuery中的Lucene查询不包含语法错误



我有一个应用程序,需要允许用户对文档执行全文搜索,并在需要时使用Lucene Query Parser语法。eXist数据库是从Django后端查询的,该后端使用eulexistdb与eXist对话。

问题是,当用户在全文搜索中使用不正确的语法时,这是在游戏后期发现的。Django应用程序必须查询SQL数据库来确定搜索的一些参数。当构建完整的XQuery并访问eXist时,SQL查询已经运行,这意味着SQL查询的成本已经花掉了。(我知道我可以将SQL端查询的数据整理到eXist中,这样就只查询eXist了。只是目前还不能选择。)

我想提前知道Lucene查询是否存在语法错误,这样我就可以避免开始查询SQL数据库。

我查看了eXist的文档,但在API中没有发现任何内容,这是一个简单的函数,用于检查全文查询在语法上是否有效。

这里有一个简单的函数,如果Lucene查询正常,它将返回True;如果查询中存在语法错误,它将返Falsedb必须是eulexistdb.db.ExistDB的实例,而query是Lucene查询:

def check(db, query):
try:
db.query(safe_interpolate("ft:query(<doc/>, {lucene_query})",
lucene_query=query))
except ExistDBException as ex:
if ex.message().startswith(
"exerr:ERROR Syntax error in Lucene query string"):
return False
raise ex # Don't swallow other problems that may occur.
return True

这应该适用于任何有提供eXist访问权限的库的语言。其想法是针对伪造文档(<doc/>)运行感兴趣的查询。使用伪造的文档可以避免实际搜索数据库。(空节点序列可能看起来更好,但我们不会针对空节点序列运行ft:query,因为这样XQuery优化器就可以跳过解析和运行Lucene查询的尝试,因为无论实际的Lucene查询是什么,对空序列的有效查询都必须返回空序列。)它是否返回任何结果都无关紧要。如果查询没有错误,那么就不会出现异常。如果查询有语法错误,则会引发异常。我没有找到比检查异常存储的错误消息更健壮的方法来检测它是Lucene语法错误还是其他错误。

(safe_interpolate函数是一个应该对lucene_query进行插值以避免注入的函数。由您决定应用程序中需要什么。)

以下是我认为与前面发布的方法互补的方法。我使用lucene-query-parser在客户端(即浏览器中)执行检查:

define(function (require, exports, _module) {
"use strict";
var lqp = require("lucene-query-parser");
function preDrawCallback() {
// We get the content of the search field.
var search = this.api().search(); 
var good = true;
try {
lqp.parse(search); // Here we check whether it is syntactically valid.
}
catch (ex) {
if (!(ex instanceof lqp.SyntaxError)) {
throw ex; // Don't swallow exceptions.
}
good = false;
}
// Some work is performed here depending on whether
// the query is good or bad.
return good;  // And finally we tell DataTables whether to inhibit the draw.
}
// ....
});

preDrawCallback与DataTables实例一起使用。返回false禁止绘制表,这也禁止执行对服务器的查询。因此,如果查询在语法上不正确,它将永远无法到达后端(definerequire调用存在,因为我的代码和lucene-query-parser都是AMD模块。)

潜在问题:

  1. 如果执行检查的库有错误或不支持Lucene支持的整个语法,它将阻止应该执行的查询。在我决定使用lucene-query-parser之前,我发现了一些有缺陷的(或者充其量是严重过时的)库。

  2. 如果客户端库恰好支持Lucene的后续版本中引入的构造,但eXist使用的版本不支持该构造。保持我在另一个答案中显示的后端检查可以确保任何可能漏网之鱼都被捕获。

最新更新