将关键字存储在查询集中,在结果查询集中提供带有 Q 对象的搜索命中以及搜索结果

Posted

技术标签:

【中文标题】将关键字存储在查询集中,在结果查询集中提供带有 Q 对象的搜索命中以及搜索结果【英文标题】:Store keywords in queryset that give search hits with Q objects in the resultant queryset along with the search results 【发布时间】:2020-09-01 06:10:55 【问题描述】:

record_list 是一个 Python 列表,其中包含要搜索的关键字列表。以下代码是我的 Django views.py,我在其中使用这些关键字搜索 mysql 数据库。代码在product_namedescription 列中搜索并返回关键字给出搜索命中的整个记录​​。

q_object = Q(product_name__icontains=record_list[0]) | Q(description__icontains=record_list[0])
for item in record_list:
   q_object.add(Q(product_name__icontains=item) & (Q(description__icontains=item)), q_object.connector)
    
queryset = Products.objects.filter(q_object).values().distinct()
    
for query in queryset:
   Filtered.objects.create(**query)

搜索结果成功保存在queryset 中,我可以将查询集保存在数据库表中。但我还想将在“查询集”中提供搜索命中的关键字与相应的搜索结果一起保存。有没有办法使用 Django Q 对象来做到这一点?

【问题讨论】:

您在表达式 & (Q(description__icontains=item)), 中可能写了一个不正确的运算符 '&' 和一个多余的括号,这与 record_list 第一项的表达式不匹配。 【参考方案1】:

我建议仅通过 Python 评估等效的 Q() 表达式。最后我会解释原因。

预计模型 Filtered 有一个 CharField keywords 并且关键字由一个字符分隔,该字符绝不是关键字的一部分,例如空格或逗号。

q_object = ~Q()  # trick: a filter with empty results
for item in record_list:
   q_object |= Q(product_name__icontains=item) | (Q(description__icontains=item))

queryset = Products.objects.filter(q_object).values().distinct()

new_items = []
for item_dict in queryset:
    used_keywords = [keyword for keyword in record_list
                     if keyword.lower() in item_dict['product_name'].lower() or
                     if keyword.lower() in item_dict['description'].lower()]
    new_items.append(Filtered(keywords=used_keywords, **item_dict))
Filtered.objects.bulk_create(new_items)

代码注释:

您的代码的最后一部分通过bulk_create() 方法而不是简单的create() 进行了优化。

显式 OR 连接器 ('|=') 优于间接连接器 q_object.connector,后者必须在阅读更多代码后最终识别为 OR。

如果不使用连接,将.values().distinct() 组合起来是没有用的,因为主键字段也是 values() 字段的一部分,并且主键在仅基于的查询集中是唯一的一张桌子。我没有删除它,因为可能一个连接隐藏在 record_list 中,可能会被更多表遍历。

为什么匹配的关键字不能直接被Q对象求值?因为 WhereNode 不能直接在 Python 中进行评估,除非通过 SQL 单独执行它们,否则它们不能成为 SQL 中 SELECT 子句的一部分。 Q 表达式非常通用且可扩展,例如通过具有许多变量的用户定义函数。因此,仅针对简单类型的表达式在 Django 中实现 Python 评估是没有意义的。通过 SQL 对每个关键字进行评估是无效的,但对于运行测试来说,SQL 和 Python 实现的结果对于某些测试用例集或在调试模式下是相同的仍然很有用,特别是如果您稍后将编辑这些 Q 表达式.

【讨论】:

以上是关于将关键字存储在查询集中,在结果查询集中提供带有 Q 对象的搜索命中以及搜索结果的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 查询集中编辑注释结果

在结果集中放置一个联合查询

如何将两个查询的结果合并到一个数据集中

游标的作用是啥?

如何从带有模板标签的查询集中访问模型属性?

忽略查询中的mysql全文停用词