Web应用程序的一个常见任务是使用用户输入搜索数据库中的某些数据。在简单的情况下,这可能是按类别过滤对象列表。更复杂的用例可能需要使用权重、分类、突出显示、多种语言等进行搜索。本文档解释了一些可能的用例和您可以使用的工具。
我们将引用 进行查询 .
基于文本的字段具有多种匹配操作。例如,您可能希望允许按如下方式查找作者:
>>> Author.objects.filter(name__contains="Terry")
[<Author: Terry Gilliam>, <Author: Terry Jones>]
这是一个非常脆弱的解决方案,因为它要求用户知道作者姓名的确切子字符串。更好的方法可能是不区分大小写的匹配 (icontains
但这只是稍微好一点。
如果您使用PostgreSQL,Django提供 a selection of database specific tools 允许您利用更复杂的查询选项。其他数据库有不同的工具选择,可能通过插件或用户定义的函数。Django目前不包括对他们的任何支持。我们将使用PostgreSQL中的一些示例来演示数据库可能具有的功能。
在其他数据库中搜索
由提供的所有搜索工具 django.contrib.postgres
完全基于公共API构建,例如 custom lookups 和 database functions . 根据数据库的不同,您应该能够构造查询以允许类似的API。如果有具体的事情不能这样做,请开一张票。
在上面的示例中,我们确定不区分大小写的查找会更有用。在处理非英语名称时,进一步的改进是使用 unaccented comparison
:
>>> Author.objects.filter(name__unaccent__icontains="Helen")
[<Author: Helen Mirren>, <Author: Helena Bonham Carter>, <Author: Hélène Joy>]
这显示了另一个问题,即我们将与名称的不同拼写进行匹配。在这种情况下,我们有一个不对称的-搜索 Helen
会捡起 Helena
或 Hélène
但不是相反。另一种选择是使用 trigram_similar
比较,比较字母序列。
例如:
>>> Author.objects.filter(name__unaccent__lower__trigram_similar="Hélène")
[<Author: Helen Mirren>, <Author: Hélène Joy>]
现在我们遇到了一个不同的问题--“海伦娜·博纳姆·卡特”这个较长的名字没有出现,因为它要长得多。Trigram搜索考虑三个字母的所有组合,并比较搜索和源字符串中出现的字母数。对于较长的名称,有更多组合没有出现在源字符串中,因此它不再被视为密切匹配。
此处正确选择比较函数取决于您的特定数据集,例如所使用的语言和要搜索的文本类型。我们所看到的所有示例都是在短字符串中,用户可能会输入与源数据相近的内容(通过不同的定义)。
当您开始考虑大块文本时,标准数据库操作不再是有用的方法。虽然上面的例子可以被认为是对字符串的操作,但全文搜索会查看实际的单词。根据使用的系统,它可能会使用以下一些想法:
忽略“a”、“the”、“and”等“停止词”。
词干,使 "pony" 和 "ponies" 被认为是相似的。
根据不同的标准对单词进行加权,例如它们在文本中出现的频率,或它们出现在其中的字段(如标题或关键字)的重要性。
使用搜索软件有很多选择,其中一些最突出的选择是 Elastic 和 Solr. 这些是基于文档的完整搜索解决方案。要将它们与来自Django模型的数据一起使用,您需要一个将数据转换为文本文档的层,包括对数据库ID的后引用。当使用引擎的搜索返回某个文档时,可以在数据库中查找该文档。有各种各样的第三方库可以帮助完成这个过程。
PostgreSQL内置了自己的全文搜索实现。虽然没有其他搜索引擎那么强大,但它的优势在于它位于数据库内部,因此可以很容易地与其他关系查询(如分类)结合在一起。
这个 django.contrib.postgres
模块提供了一些帮助程序来进行这些查询。例如,一个查询可能会选择所有提到“奶酪”的博客条目:
>>> Entry.objects.filter(body_text__search="cheese")
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]
您还可以根据字段组合和相关模型进行筛选:
>>> Entry.objects.annotate(
... search=SearchVector("blog__tagline", "body_text"),
... ).filter(search="cheese")
[
<Entry: Cheese on Toast recipes>,
<Entry: Pizza Recipes>,
<Entry: Dairy farming in Argentina>,
]
见 contrib.postgres
全文搜索 有关完整详细信息的文档。
7月 22, 2024