使用Django查询集搜索一个列中的多个单词

4
我是一名有用的助手,可以为您翻译文本。
我有一个自动完成框,需要返回具有输入单词的结果。但是,输入的单词可以是部分匹配的,并且位于不同的顺序或位置。
例如:
数据库列(MySQL)中的值-
Expected quarterly sales
Sales preceding quarter
Profit preceding quarter
Sales 12 months

现在,如果用户输入季度销售额,则应同时返回前两个结果。
我尝试过:
column__icontains = term  #searches only '%quarter sales% and thus gives no results
column__search = term  #searches any of complete words and also returns last result
**{'ratio_name__icontains':each_term for each_term in term.split()}   #this searches only sales as it is the last keyword argument

有没有通过正则表达式或者Django内置的方法来解决这个常见的模式问题?请注意,不需要解释,只需翻译。保留HTML标签。

1
也许我错了,但这看起来更像是一个全文搜索问题。你应该查看一下MySQL全文搜索,并看看它是否符合你的需求。 - Manoj Govindan
1
你尝试过使用任何搜索引擎吗?看看 haystack(http://haystacksearch.org/)。它支持 whoosh,这在开始时非常容易使用,而且更多功能也很强大。 - szaman
嗨,Manoj,我确实尝试了全文搜索,但它返回具有上述任何单词的结果。例如,它还会返回“销售12个月”(它不应该这样)。 - Pratyush
2个回答

9

搜索引擎在这方面更加高效,但您仍然可以使用基本代码完成此任务。如果您正在查找包含“A”和“B”的字符串,则可以:

Model.objects.filter(string__contains='A').filter(string__contains='B')

或者

Model.objects.filter(Q(string__contains='A') & Q(string__contains='B'))

但实际上,你最好选择一个简单的全文搜索引擎,配置较少,比如Haystack/Whoosh。


如果您不想设置完整的文本搜索引擎,现在的数据库都带有内置的全文搜索功能。Django目前支持Postgres,您也可以手动添加其他数据库的支持。当然,内置的全文搜索功能可能不如专用搜索引擎好,但它仍然比为每个单词链接过滤器要好得多。 - xyres

1

上述使用链式.filter()的答案要求所有条目都匹配过滤器。

对于那些想要"包含或"或任何类型行为的人,可以使用functools.reduce来链接django的Q运算符以获取搜索项列表:

from functools import reduce

from django.db.models import Q

list_of_search_terms = ["quarter", "sales"]
query = reduce(
    lambda a, b: a | b,
    (Q(column__icontains=term) for term in list_of_search_terms),
)
YourModel.objects.filter(query)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接