4

我正在尝试在 django 中为 postgres db 的模型添加标签,我找到了两个解决方案:

使用外键:

class Post(models.Model):
    tags = models.ManyToManyField('tags')
    ...

class Tag(models.Model):
    name = models.CharField(max_length=140)

使用数组字段:

from django.contrib.postgres.fields import ArrayField

class Post(models.Model):
    tags = ArrayField(models.CharField(max_length=140))
    ...

假设我不关心在我的代码中支持其他数据库后端,推荐的解决方案是什么?

4

2 回答 2

7

如果您使用 Array 字段,

  • 数据库中每一行的大小会有点大,因此 Postgres 将使用更多的toast 表

  • 每次获取该行时,除非您专门使用延迟字段或仅通过值或其他方式将其从查询中排除,否则您每次遍历该行时都要支付加载所有这些值的成本。如果这就是你需要的,那就这样吧。

  • 根据该数组中的值进行过滤,虽然可能不会那么好,并且 Django ORM 并不像 M2M 表那样明显。

如果您使用 M2M 领域,

  • 您可以更轻松地过滤这些相关值这些字段默认情况下会被推迟,如果需要它们可以使用 prefetch_related ,如果您只想加载这些值的子集,则可以使用。

  • 由于键和额外的 id 字段,使用 M2M 的数据库中的总存储量将略高。

  • 在这种情况下,由于键的原因,连接的成本完全可以忽略不计。

话虽如此,上面的答案不属于我。前段时间,我在学习 Django 时偶然发现了这个困境。我在这个问题中找到了答案,Django Postgres ArrayField vs One-to-Many relationship

希望你得到你正在寻找的东西。

于 2017-06-06T09:59:58.370 回答
3

如果您希望监控类标签(例如:有多少标签,有多少特定标签等),请选择第一个选项,因为您可以向模型添加更多字段并为应用程序添加丰富性。

另一方面,如果您只是为了显示或最小化处理而希望它是一个数组列表,请选择该选项。

但是,如果您希望节省时间并为应用程序增加丰富性,您可以使用这个

https://github.com/alex/django-taggit

初始化就这么简单:

from django.db import models

from taggit.managers import TaggableManager

class Food(models.Model):
# ... fields here

    tags = TaggableManager()

并且可以通过以下方式使用:

>>> apple = Food.objects.create(name="apple")
>>> apple.tags.add("red", "green", "delicious") 
>>> apple.tags.all()
[<Tag: red>, <Tag: green>, <Tag: delicious>]
于 2017-06-06T06:59:24.173 回答