Django 通过最多包含两个单词的 CharField 过滤对象

Django filter objects by CharField containing at most two words

我在这样的模型中记录所有用户搜索查询:

class SearchLog(models.Model):
     query = models.CharField(max_length=512)
     datetime = models.DateTimeField(auto_now_add=True, db_index=True)

为了获得最多包含一个词的所有查询,我创建了这个查询集:

SearchLog.objects.exclude(query__contains=" ")

我想获取最多包含两个词的查询。即使是原始 sql 也有吗?

为此可以使用 regular expression (regex)。这是您描述的文本模式。

例如,要匹配 most 两个单词,正则表达式可能如下所示:

^\S+(\s+\S+)?$

(但视情况而定,可能需要稍作改动)

\S代表非space字符(即没有space、制表符、换行等)。我们重复这些字符一次或多次(使用 + 量词)。接下来我们可选地允许第二个词(即末尾问号 ? 的意思)。这个新词由一个或多个 连续 间距字符(\s+)和一个或多个非 space 字符(\S+)组成.插入符号 (^) 和美元符号 ($) 锚点表示字符串的开头和结尾(没有它,它将匹配任何至少有一个单词的内容)。如前所述,其中一个问题可能是您所看到的单词,因此根据该规范,您可能需要稍微更改一下正则表达式。

例如,如果根本没有单词的查询也应该被匹配,我们必须将其更改为 ^(\S+(\s+\S+)?)?$ 但是只有空格的字符串仍然不会被匹配。您会发现很难完全正确地获得模式,因为它基本上取决于您认为什么是“匹配”,什么不是。

您可以使用 regex101 测试正则表达式。匹配的字符串是突出显示的行。包含三个或更多单词的行 突出显示,因此正则表达式会排除这些。您可以使用此工具测试正则表达式,并对其进行更改,直到它完全符合您的要求。

所以我们可以过滤:

SearchLog.objects.filter(query<b>__regex=r'^\S+(\s+\S+)?$'</b>)

正则表达式能够执行相当高级的匹配。然而,在计算机科学中,有一个著名的“常规语言的抽取引理”,它指定某些模式族 can 不能写成正则表达式(事实上,有一些模式根本无法被任何程序匹配)。在这里这无关紧要(我认为),但是正则表达式本身不能匹配程序员心中的任何模式。