【问题标题】:Django Querysets: Ordering posts by number of similar tagsDjango Querysets:按相似标签的数量排序帖子
【发布时间】:2021-07-26 05:47:13
【问题描述】:

假设我有一个 Django 模型:

帖子 - 代表博客帖子 Tag - 代表一个规范的标签。让我们假设它是一个标签。 PostTag - 帖子和标签之间的外键中介。

现在假设我有 5 个带有这些标签的帖子:

  1. #food #story #recepie #gardening #entre

  2. #food #story #recepie #ham # 三明治

  3. #food #story #flowers #fish #sushi

  4. #food #story #computer #keyboard #mouse

  5. #food #coffee #vitamins #basil #citrus

--

给定帖子 1 有 5 个标签,我如何获得 N 个标签最相似的其他帖子?

Posts.objects.filter(publish_at__gte=somedatetime).order_by("similarity")

【问题讨论】:

    标签: python django django-queryset


    【解决方案1】:

    其中一个解决方案可能是编写自定义 ModelManager,它使用 difflib.get_close_matches() 过滤其他帖子(您需要转换为字符串列表或类似的东西)

    或者也许更简单的解决方案,但我不确定你会得到你需要的;在Django的“Q”对象中使用icontains进行过滤并将它们组合起来。

    【讨论】:

    • 知道其他服务现在如何做到这一点吗?似乎是一个很好理解/解决的问题,但这些似乎有点像黑客。另一种选择是为每个帖子运行计算计算,但这在大型社交网络上似乎也有点疯狂。
    • 我认为不使用一些 ML 就没有简单的解决方案。标签是数据库中与 Post 的多对多关系,而不是 CharField 或 TextField 作为 # 分隔的单词。您需要至少将主题标签 A 和主题标签 B 的查询组合为包含集,以便您可以找到哪些帖子具有给定标签。
    • 但这需要很多查询。我认为标准解决方案是使用 ElasticSearch
    • 对不起,如果这没有帮助你! :C
    【解决方案2】:

    您可以在annotate() 每个Post 中使用与当前帖子匹配的标签中的Count。然后,您可以使用该带注释的字段进行排序。

    from django.db.models import Count, Q
    
    post = Post.objects.first()
    
    similar_posts = Post.objects.filter().annotate(
        similar_tags=Count('tags', filter=Q(tags__in=post.tags.all()))
    ).order_by('-similar_tags')[:5]
    

    添加一个切片 [:5] 会在查询中添加一个 LIMIT 5(如果我们只对 5 个最相似的帖子感兴趣)。

    这个例子基于一个简单的模型定义:

    class Post(models.Model):
        tags = models.ManyToManyField('PostTag')
    
    
    class PostTag(models.Model):
        name = models.CharField(max_length=255, unique=True)
    
        def __str__(self):
            return self.name
    

    【讨论】:

    • 过滤器(=Q(tags__in=post.tags.all())) 将过滤所有与当前帖子有共同标签的帖子;但是,所有这些过滤后的帖子不会也保留它们不相关的标签吗?因此,当您计算“标签”时,您最终不会计算所有标签吗?例如,在 OP 的示例中,如果我们试图找到类似于帖子 1 的帖子,并且通过上面的 Q 过滤器,帖子 2 会被过滤,那么过滤后的帖子是否也会保留 #ham #sandwich (不存在在帖子 1)中?
    • @Rishi 该问题询问如何构造一个查询,以检索“N 个具有最相似标签的其他帖子”。我的答案中的代码正是问题所要求的,我用他们的例子对其进行了测试——它用相似标签的数字计数来注释每个帖子,以便可以将排序应用于查询。该问题没有询问如何确保在每个单独的对象中都可以访问一组过滤标签(这就是您要问的)。实现起来并不难,但问题并没有要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 2021-11-10
    • 2021-10-05
    相关资源
    最近更新 更多