搜索¶
Web应用程序的一个常见任务是使用用户输入在数据库中搜索一些数据。在简单的情况下,这可以是通过类别过滤对象的列表。更复杂的用例可能需要使用加权,分类,突出显示,多种语言等进行搜索。本文档解释了一些可能的用例和可以使用的工具。
我们将参考在 进行查询 中使用的相同模型。
用例¶
标准文本查询¶
基于文本的字段具有简单匹配操作的选择。例如,您可能希望允许查找像这样的作者:
>>> Author.objects.filter(name__contains='Terry')
[<Author: Terry Gilliam>, <Author: Terry Jones>]
这是一个非常脆弱的解决方案,因为它需要用户知道作者姓名的确切子字符串。更好的方法可以是不区分大小写的匹配(icontains
),但这只是稍微好一点。
一个数据库的更高级的比较函数¶
如果你使用PostgreSQL,Django提供 选择数据库特定的工具 允许你利用更复杂的查询选项。其他数据库具有不同的工具选择,可能通过插件或用户定义的函数。 Django目前不支持他们。我们将使用PostgreSQL中的一些示例来演示功能数据库可能具有的类型。
在其他数据库中搜索
django.contrib.postgres
提供的所有搜索工具都完全在公共API(如 自定义查找 和 数据库函数)上构建。根据您的数据库,您应该能够构造查询以允许类似的API。如果有具体的事情不能这样做,请打开一张票。
在上面的例子中,我们确定不区分大小写的查找会更有用。在处理非英语名字时,进一步的改进是使用 unaccented comparison
:
>>> Author.objects.filter(name__unaccent__icontains='Helen')
[<Author: Helen Mirren>, <Author: Helena Bonham Carter>, <Actor: 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>, <Actor: Hélène Joy>]
现在我们有一个不同的问题 - “海伦娜·伯翰·卡特”的更长的名字没有显示,因为它是更长的。 Trigram搜索考虑三个字母的所有组合,并比较在搜索和源字符串中出现的数量。对于较长的名称,源字符串中出现更多的组合,因此不再被认为是紧密匹配。
这里比较功能的正确选择取决于您的特定数据集,例如使用的语言和正在搜索的文本的类型。我们所看到的所有例子都是短字符串,用户可能会通过不同的定义输入到源数据。
基于文档的搜索¶
当你开始考虑大块文本时,简单的数据库操作太简单了。而上面的例子可以被认为是对字符串的操作,全文搜索查看实际的字。根据使用的系统,它可能使用以下一些想法:
忽略诸如“a”,“the”,“and”的“停用词”。
停止词,使“小马”和“小马”被认为是类似的。
根据不同标准(例如在文字中显示的频率或字段(例如标题或关键字)的重要性)对字词加权字词。
有许多使用搜索软件的替代方法,一些最突出的是 Elastic 和 Solr。这些是完整的基于文档的搜索解决方案。要将它们与Django模型中的数据结合使用,您需要一个将数据转换为文本文档的层,包括对数据库ID的反向引用。当使用引擎的搜索返回某个文档时,您可以在数据库中查找。有各种第三方库,旨在帮助这个过程。
PostgreSQL支持¶
PostgreSQL有自己的全文搜索实现内置。虽然没有一些其他搜索引擎那么强大,但它的优点是位于数据库内部,因此可以轻松地与其他关系查询(如分类)结合使用。
django.contrib.postgres
模块提供了一些帮助器来进行这些查询。例如,一个简单的查询可能是选择所有提到“cheese”的博客条目,:
>>> 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
全文搜索 文档。