在启动我想要运行的完整 XQuery 之前,如何验证嵌入在较大 XQuery 中的 Lucene 查询不包含语法错误?
Posted
技术标签:
【中文标题】在启动我想要运行的完整 XQuery 之前,如何验证嵌入在较大 XQuery 中的 Lucene 查询不包含语法错误?【英文标题】:How can I verify that a Lucene query embedded in a larger XQuery does not contain a syntax error before launching the complete XQuery I want to run? 【发布时间】:2016-10-06 12:32:32 【问题描述】:我有一个应用程序,我需要允许用户对文档执行全文搜索,并在需要时使用Lucene Query Parser syntax。 eXist 数据库是从使用eulexistdb 与 eXist 对话的 Django 后端查询的。
问题在于,当用户使用不正确的语法进行全文搜索时,这会在游戏后期被发现。 Django 应用程序必须查询 SQL 数据库以确定搜索的某些参数。在构建完整的 XQuery 并访问 eXist 时,SQL 查询已经运行,这意味着 SQL 查询的成本已经花费。 (我知道我可以将在 SQL 端查询的数据编组到 eXist 中,以便只查询 eXist。现在不是一个选项。)
我想提前知道 Lucene 查询是否存在语法错误,我可以避免开始查询 SQL 数据库。
我查看了 eXist 的文档,但在 API 中没有找到任何可以检查全文查询在语法上是否有效的简单函数。
【问题讨论】:
【参考方案1】:我认为这是一种与我 posted earlier 互补的方法。我正在使用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
禁止绘制表格,这也禁止执行对服务器的查询。所以如果查询在语法上不正确,它永远不会到达后端。(define
和 require
调用在那里,因为我的代码和 lucene-query-parser
都是 AMD 模块。 )
潜在问题:
如果执行检查的库有问题或不支持 Lucene 支持的全部语法,它将阻止应该通过的查询。在我决定使用lucene-query-parser
之前,我发现了一些有缺陷(或充其量是严重过时)的库。
如果客户端库碰巧支持在更高版本的 Lucene 中引入但在与 eXist 一起使用的版本中不支持的构造。保留我在另一个答案中显示的后端检查可以确保将任何可能漏掉的东西都捕获到那里。
【讨论】:
【参考方案2】:这是一个简单的函数,如果 Lucene 查询正常,它将返回 True
,如果查询中有语法错误,则返回 False
。 db
必须是 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
以避免注入的函数。由您决定您的应用程序中需要什么。)
【讨论】:
我很想知道是否有更直接的东西我设法错过了。 另一种选择是为 Python 中的 Lucene 语法编写自己的小型语法检查器或解析器,这样您就无需访问 eXist 即可知道语法是否正确。 我最终可能会最终决定这样做。以上是关于在启动我想要运行的完整 XQuery 之前,如何验证嵌入在较大 XQuery 中的 Lucene 查询不包含语法错误?的主要内容,如果未能解决你的问题,请参考以下文章