为Google的全文搜索服务转义搜索查询

This is a cross-post of https://groups.google.com/d/topic/google-appengine/97LY3Yfd_14/discussion

我正在使用gae 1.6.6中的全新全文搜索服务,并且在将它们传递给搜索索引之前,我很难弄清楚如何正确地转义我的查询字符串。文档提到某些字符需要转义(即数字运算符),但是他们没有指定查询解析器如何期望字符串被转义。

我遇到的问题有两方面:

  1. Failing to escape the crap out of many characters (more than those that are hinted at in the docs) will cause the parser to raise a QueryException.
  2. When I've escaped the query to the point it won't raise, the numeric operators (>, <, >=, <=) no longer parse correctly (not factored into the search).

我设置了一个测试,将 string.printable 提供给 my_index.search(),并发现它会在每个“可打印的对象上引发 QueryException “控制角色,我现在正在剥离,以及看起来像星号,逗号,括号,括号,代字号等无辜的东西。这些都没有在文档中提到需要逃脱。

到目前为止我已经尝试过:

  • cgi.escape()
  • saxutils.escape() with a mapping of ascii to urlencoded equivalents (eg , -> %2C)
  • saxutils.escape() with a mapping of ascii to html entity encoded ascii codes (eg {)
  • urllib.quote_plus()

I've gotten the best results so far using url-style(%NN) replacements, but >, <, >=, and <= continue to fail to yield the expected results from the index. Also, and this doesn't really seem to have anything to do with the escaping issue, but using NOT in front of a field = value type query seems to not be working as advertised either.

TL;博士

在将查询发送到搜索服务之前,我应该如何逃避查询,以便解析器不会引发 QueryException 查询会产生预期结果?

0
额外 编辑
意见: 1

1 答案

作为简单的文档中解释( https://developers.google.com/ AppEngine上/文档/蟒蛇/搜索/概述#Query_Language_Overview ),查询参数是必须符合我们的查询语言的字符串。我们应该记录好。

现在,我建议你用双引号将你的查询(或至少一些单词/术语)包装起来。这样你就可以传递所有可打印的字符,但“和。下面的例子显示了结果。

import string
from google.appengine.api.search import Query
Query('"%s"' % string.printable.replace('"', '').replace('\\', ''))

而且你甚至可以传递不可打印的字符

Query('"%s"' % ''.join(chr(i) for i in xrange(128)).replace('"','').replace('\\', ''))

EDIT: Note that anything that is enclosed in double quotes is an exact match, that is "foo bar" would match against ...foo bar... but no ...bar foo..

0
额外
有可能提供一个更实用的例子吗?给定一个类似于 created> = 2009-20-13 AND description:foobar 的查询,你会如何避免这种情况?
额外 作者 Owen Nelson,
好吧,我开始看到了。这确实是上下文的(正如我在我的小组帖子中提到的那样)。 foo> = 123 不需要干预,但 foo> = 123> 会引发异常。看来我需要构建一个预解析器解析器才能完全处理它。这是......尴尬。
额外 作者 Owen Nelson,
另外,即使在提供一个公民的,格式良好的查询时,大于,小于我的日期字段也不会起作用。
额外 作者 Owen Nelson,
我有点看到你要去那个问题。我现在正在查看两种不同的上下文来运行查询:第一种是当我为用户准备查询时(安全,不需要转义),第二种查询来自用户(我应该是当它进来时残酷地剥去刺和刺)。
额外 作者 Owen Nelson,
此答案通过删除实际上可能是查询的一部分的任何双引号来更改原始搜索词。相反,我正在成功使用以下替换项,它只是在搜索项内跳过任何双引号:search_term.replace('“','\\”')
额外 作者 Nick Franceschina,
您提供的查询不需要转义Query('created> = 2009-20-13 AND description:foobar')正常工作。如果实际上在文档中查找字符串'created> = 2009-20-13 AND description:foobar',则应该将该字符串括在引号中。但是,如果我想将它们用作字符而不是运算符,通常我会在双引号中包含文档中定义的任何运算符。
额外 作者 Sebastian Kreft,
我假设你从最终用户接收查询字符串。对?
额外 作者 Sebastian Kreft,
这个答案从2012年开始,现在提到“现在”。现在有更好的方法来做到这一点吗?用引号包装并不是一个理想的解决方案,因为它会查找确切的字符串
额外 作者 manubot,