【问题标题】:How to better format Django filter query for +1000 entries using SQLite3 database? (Expression tree is too large (maximum depth 1000))如何使用 SQLite3 数据库更好地格式化 +1000 个条目的 Django 过滤器查询? (表达式树太大(最大深度1000))
【发布时间】:2022-01-04 06:25:20
【问题描述】:

我拥有的 Django 模型是组件和产品。组件将产品作为其外键。 我正在从 request.GET 中检索一个名为“组件”的搜索参数,该参数包含一个可以属于任何组件的子字符串列表。根据匹配的组件,我想检索具有此组件的所有产品并将其返回给客户端。我的 SQLite 数据库中大约有 12000 个组件和 3000 个产品

我一直在过滤掉带有“|”的产品每个组件的产品 ID 号的运算符,在搜索特定组件子字符串时可以正常工作,例如“乳糖”和“细菌”。

但是,当我搜索较短的子字符串时,例如“ac”,我收到错误消息:“OperationalError at /search, Expression tree is too large (maximum depth 1000)”。

据我了解,这是因为数据库正在执行大量联合查询,其中超过 1000 个查询会导致该错误。

我想知道如何修复或解决此错误。有没有更好的方法来使用 Django 的过滤查询?

这是我的models.py:

from django.db import models

class Product(models.Model):
    id_number = models.IntegerField(primary_key=True)
    product_name = models.CharField(max_length=200)

class Component(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)

这是我对views.py的摘录:

query = Product.objects.all()
if 'components' in request.GET and len(request.GET['components']) > 0:
    component_queries = request.GET['components'].strip().split(",") # List of all components as strings
    components = Component.objects.all() # Roughly 12000 entries in total, roughly 1700 entries for a worst case after filtering
    for component_query in component_queries:
        components &= (Component.objects.filter(name__icontains=component_query)
    if len(components) == 0:
        query = Product.objects.none()
    specified_products = Product.objects.none()
    for component in components:
        specified_products |= Product.objects.filter(id_number__icontains=component.product.id_number)
    query &= specified_products

为了验证错误是否在摘录中,我将 for 循环中的组件数量限制为少于 1000 个,并且搜索引擎运行良好。

【问题讨论】:

    标签: python django sqlite


    【解决方案1】:

    您可以使用以下方式过滤:

    from django.db.models import Q
    
    component_queries = request.GET['components'].strip().split(',')
    
    Product.objects.filter(
        Q(*[
           Q(component__name__icontains=component_query)
           for component_query in component_queries
        ])
    )

    然而,上面将只检索具有与 all component_querys 匹配的组件的Products。

    如果您想查找至少有一个与字符串匹配的组件的产品,您可以使用:

    from django.db.models import Q
    
    component_queries = request.GET['components'].strip().split(',')
    
    Product.objects.filter(
        Q(*[
           Q(component__name__icontains=component_query)
           for component_query in component_queries
           ],
           _connector=Q.OR
        )
    ).distinct()

    .distinct() [Django-doc] 将阻止多次检索Product,因为有匹配的组件。

    【讨论】:

    • 它有效,谢谢!我没有意识到您可以在检索模型时进行列表理解。我将进一步研究 Q 模块,了解它如何比我尝试的方法更有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-29
    • 2014-02-03
    • 2011-07-12
    • 1970-01-01
    • 2017-12-26
    相关资源
    最近更新 更多