在resources.py中我有:
from every e1=FooStream -> e2=BarStream[math:abs( e1.timestamp - e2.timestamp ) <= 5*6000]
within 10 sec
select e1.timestamp, e2. ...
insert into OutputStream;
from every e1=BarStream -> e2=FooStream[math:abs( e1.timestamp - e2.timestamp ) <= 5*6000]
within 10 sec
select e1.timestamp, e2. ...
insert into OutputStream;
6个类别中约有5000个项目。当我正在制作&#39; list&#39; api请求即&#39; api / 1.0 / category&#39;,它对数据库进行大约5000次查询。我该如何优化它?我知道full = False,但它并不适合我的需要。
UPD: 我找到了导致如此多查询的原因。我有类别&#39; ItemResource中的关系,因此tastypie为每个项生成一个select查询。
class CategoryResource(ModelResource):
items = fields.ToManyField('ItemResource', 'items', full=True, null=False, readonly=True, related_name='items')
class Meta:
queryset = Category.objects.all().order_by('id')
include_resource_uri = False
always_return_data = True
resource_name = 'category'
当我请求CategoryResource时,显然这是不必要的数据,有没有办法将它从查询中排除?
答案 0 :(得分:4)
试试这个:
def get_object_list(self, request):
return super(CategoryResource, self).get_object_list(request) \
.prefetch_related('items', 'items__categories')
不要使用select_related
,因为它会返回重复的行。
prefetch_related
发出一个查询,返回所有项目,Django ORM将其与正确的行匹配。
更改dehydrate_categories
def dehydrate_categories(self, bundle):
return [category.name for category in bundle.obj.categories.all() if category.owner == bundle.request.user]
答案 1 :(得分:3)
如果仍有问题,可能是ItemResource还有一个或多个相关字段。如果是这种情况,您可以执行以下操作:
def get_object_list(self, request):
return super(CategoryResource, self).get_object_list(request).prefetch_related('items__relatedfield1', 'items__relatedfield2')
请注意,select_related
上执行的任何查询集更改(例如prefetch_related
或ItemResource
)都不会影响CategoryResource
上相关模型的查询。
更新: 尝试这样的事情:
class CategoryResource(ModelResource):
items = fields.ToManyField('ItemResource', 'items', full=True, null=False, readonly=True, related_name='items')
class Meta:
queryset = Category.objects.all().order_by('id')
include_resource_uri = False
always_return_data = True
resource_name = 'category'
def get_object_list(self, request):
return super(CategoryResource, self).get_object_list(request) \
.prefetch_related('items', 'items__categories')
class ItemResource(ModelResource):
categories = fields.ToManyField(CategoryResource, 'categories', null=True, readonly=True)
def dehydrate_categories(self, bundle):
categories = items__item=bundle.obj.categories.all()
return [
category.name
for category in categories
if category.owner_id == bundle.request.user.id
]
OR:
class CategoryResource(ModelResource):
items = fields.ToManyField('ItemResource', 'items', full=True, null=False, readonly=True, related_name='items')
class Meta:
queryset = Category.objects.all().order_by('id')
include_resource_uri = False
always_return_data = True
resource_name = 'category'
def get_object_list(self, request):
return super(CategoryResource, self).get_object_list(request) \
.prefetch_related(
'items',
Prefetch('items__categories', queryset=Category.objects.filter(owner_id=bundle.request.user.id))
)
class ItemResource(ModelResource):
categories = fields.ToManyField(CategoryResource, 'categories', null=True, readonly=True)
def get_object_list(self, request):
return super(ItemResource, self).get_object_list(request) \
.prefetch_related(
Prefetch('categories', queryset=Category.objects.filter(owner_id=bundle.request.user.id))
)
def dehydrate_categories(self, bundle):
return [
category.name
for category in bundle.obj.categories.all()
]
此外,您可以使用ListField而不是ToManyField for ItemResource.categories,因为您手动处理脱水。