django taggit similar_objects查询速度很慢

时间:2015-03-31 00:26:24

标签: python mysql django django-taggit

我正在尝试选择3个最近发布的项目,其中任何标签与当前项目类似(以及其他一些过滤器) 无法找到一种有效的方法,有很多项目'在DB。

from taggit_autosuggest.managers import TaggableManager

class Item(models.Model):
    publish_date = DateField()
    tags = TaggableManager()
    sites = ManyToManyField(Site)

def my_view():
    ...
    current_item = #get current item
    related_items = Item.active_objects.filter(
        sites=current_site,
        id__in=[x.id for x in current_item.tags.similar_objects()]
        ).order_by('-publish_date')[:3]
    ...

但是这会从similar_objects()方法导致相当大的性能问题。 current_item具有的标签越多,指数越差

# Query_time: 20.613503  Lock_time: 0.000182 Rows_sent: 83  Rows_examined: 7566504
SELECT `taggit_taggeditem`.`content_type_id`, `taggit_taggeditem`.`object_id`, COUNT(`taggit_taggeditem`.`id`) AS `n` FROM `taggit_taggeditem` WHERE (NOT (`taggit_taggeditem`.`object_id` = 205636  AND `taggit_taggeditem`.`content_type_id`
 = 11 ) AND (`taggit_taggeditem`.`tag_id`) IN (SELECT DISTINCT `taggit_tag`.`id` FROM `taggit_tag` INNER JOIN `taggit_taggeditem` ON ( `taggit_tag`.`id` = `taggit_taggeditem`.`tag_id` ) WHERE (`taggit_taggeditem`.`object_id` = 205636  AND
 `taggit_taggeditem`.`content_type_id` = 11 ))) GROUP BY `taggit_taggeditem`.`content_type_id`, `taggit_taggeditem`.`object_id` ORDER BY `n` DESC;

我也尝试过不使用类似对象方法

related_items = Item.active_objects.filter(
    sites=current_site,
    tags__in=current_item.tags.all()).exclude(slug=slug).order_by('-publish_date').distinct()[:3]
    context['tagged'] = tags.order_by('-publish_date').distinct()[:3] 

总是更糟糕(有些查询高达120秒,不好意思)

' nice'这样做的方法?!

3 个答案:

答案 0 :(得分:5)

我的假设是获取标签,并使用标签 - >项目关系比搜索所有项目更有效。 因此,我们构建了所有TaggedItem的查询集,获取所有对象的ID,然后执行我们的过滤器。

from taggit.models import TaggedItem
related_items = TaggedItem.objects.none()
for tag in current_item.tags.all():
    #build queryset of all TaggedItems
    related_items |= tag.taggit_taggeditem_items.all()

#TaggedItem doesn't have a direct link to the object, have to grab ids
ids = related_items.values_list('object_id', flat=True)
return Item.objects.filter(id__in=ids, sites=current_site).exclude(id=item.id).order_by('-publish_date')[:3]

答案 1 :(得分:1)

我正在使用以下(我希望%重叠,因此hocus-pocus与job_tags_len)。

<a href="tel:{{contacts?.phoneNumber}}" class="number">{{contacts?.phoneNumber | phone}}</a>

答案 2 :(得分:0)

我认为你可以这样做:

related_items = current_item.tags.similar_objects().filter(
    sites=current_site,
).order_by('-publish_date')[:3]

虽然我认为您必须在该过滤器中再次包含active_objects后面的逻辑。