仅在 Django 查询中进行全字匹配
Posted
技术标签:
【中文标题】仅在 Django 查询中进行全字匹配【英文标题】:Whole-word match only in Django query 【发布时间】:2013-02-06 11:57:21 【问题描述】:我正在尝试编写一个仅匹配整个单词的 Django 查询。根据here 的回答,我尝试过类似的方法:
result = Model.objects.filter(text__iregex='\bsomeWord\b')
但这并没有返回预期的结果。我也试过了
result = Model.objects.filter(text__iregex=r'\bsomeWord\b')
无济于事。我的最终目标是也能够传入一个字符串变量,例如:
result = Model.objects.filter(text__iregex=r'\b'+stringVariable+r'\b')
或
result = Model.objects.filter(text__iregex=r'\b %s \b'%stringVariable)
但现在我什至无法让它与原始字符串一起使用。我正在使用 PostgreSQL。
【问题讨论】:
【参考方案1】:当你使用 PostgreSQL 时,使用“\y”而不是“\b”,这是因为 Django 将你的正则表达式直接传递给 PostgreSQL——所以你的RegEx 需要与之兼容。您应该可以从psql
执行它们而不会出现任何问题。
result = Model.objects.filter(text__iregex=r"\y0\y".format(stringVariable))
见https://www.postgresql.org/docs/9.1/functions-matching.html#POSIX-CONSTRAINT-ESCAPES-TABLE
【讨论】:
Django 不会将 PCRE 转换为 PostgreSQL 正则表达式(请参阅:bit.ly/ZtpbgH)。所以你只需要使用 PostgreSQL 的原生正则表达式,看这里:bit.ly/ZtpojU 这行得通。感谢您添加关于\y
的解释。至于'0'.format(stringVariable)
部分,这只是'%s'%stringVariable
的另一种写法吗?两者似乎都对我有用。
是的,实际上他们都做同样的事情。我只使用 .format()
方式,因为 Python 3 需要它 (python.org/dev/peps/pep-3101)。【参考方案2】:
你也许可以通过删除正则表达式并使用一些 django 查找来获得一些东西
result = Model.objects.filter(Q(text__contains=' someword ') |
Q(text__contains=' someword.') |
Q(text__istartswith = 'someword.' |
Q(text__istartswith = 'someword.' |
Q(text__iendswith = 'someword')
有关文档,请参阅 here。
我意识到这不是那么优雅(但如果您不是正则表达式的粉丝,那么维护起来很容易)。
【讨论】:
因为这不会执行全字匹配;例如,如果我执行text__contains='tart'
,我会选择start
这样的结果。
我的错 - 我显然对 sql 不够熟悉,无法知道“全词匹配”意味着特定的东西。无论如何,我已经更新了我的答案以改进它。
易于维护?有很多情况你没有涵盖(在()
、逗号等之间)。
如果您不喜欢正则表达式,则易于维护。你不需要知道 django 或 python 来阅读这个 - 但我必须引用任何解决这个问题的正则表达式。是的,这并不能涵盖所有内容 - 只有当您确信文本仅包含该语言的一个子集时,它才会起作用。【参考方案3】:
我在尝试使用与 Perl 兼容的转义序列 \b 匹配单词边界时遇到了同样的问题。我的后端数据库是 mysql。
我通过字符类表达式[[:space:]]解决了这个问题,例如
q_sum = Q()
search_list = self.form.cleaned_data['search_all'].split(' ');
for search_item in search_list:
search_regex = r"[[:space:]]%s[[:space:]]" % search_item
q_sum |= Q(message__iregex=search_regex)
queryset = BlogMessages.objects.filter(q_sum).distinct()
【讨论】:
这不包括标点符号。以上是关于仅在 Django 查询中进行全字匹配的主要内容,如果未能解决你的问题,请参考以下文章
“ContentType 匹配查询不存在” - 仅在 SQLite 上,而不是 MySQL