【问题标题】:How to grab one random item from a database in Django/postgreSQL?如何从 Django/postgreSQL 的数据库中获取一个随机项目?
【发布时间】:2012-02-19 22:56:29
【问题描述】:

所以我得到了 database.objects.all() 和 database.objects.get('name') 但是我如何从数据库中获取一个随机项目。我在试图弄清楚如何获得它而不是选择一个随机项目时遇到了麻烦。

【问题讨论】:

    标签: python django postgresql


    【解决方案1】:

    从所有数据库对象的列表中选择一个随机元素并不是一个 goog 解决方案,因为检索数据库的所有元素会对性能产生很大影响,order_by('?') 也不会像 django documentation 中提到的那样使用。

    最好的解决办法应该是用随机索引检索一个元素:

    import random
    
    random_idx = random.randint(0, Model.objects.count() - 1)
    random_obj = Model.objects.all()[random_idx]
    

    【讨论】:

    • 你不觉得 Model.objects.all() 很贵吗?见我编辑的答案。
    • 您是否有解释/基准表明这比 order_by('?')[0] 更快?我知道文档说什么,但这里的关键是数据库将只选择一项,因此速度实际上是相同的(给定一个相当智能的数据库引擎)。 order_by('?') 仅当您实际获取多于一行时才会非常慢..
    • @AamirAdnan:当然,成本取决于您的记录数量,并且它可能适用于少数记录,但如果您使用 values_list 并且您会说数百万记录中,django 需要获取每个对象的id
    • @Delyan:数据库必须对所选表中的所有记录应用随机排序,然后才能检索第一个元素!一篇关于mysql的文章:jan.kneschke.de/projects/mysql/order-by-rand
    • @lazerscience:我的立场是正确的,你是对的。有点。 :) 看到这个要点 - gist.github.com/1868909 - 我在 SQL 中重新创建了 Python 代码以避免 Python 和 Postgres 之间的跳转。我正在运行它的表很小,但需要注意的重要一点是 ORDER BY RANDOM() 的执行时间始终很慢。随机偏移替代方案的运行时间取决于随机索引本身!按索引排序(即强制索引扫描)使结果更加一致,但仍随偏移量而变化。但是是的,你是对的,它更快。
    【解决方案2】:

    Aamir 的解决方案将选择所有对象,然后丢弃除一个之外的所有对象。这非常浪费,而且这种计算应该在数据库中完成。

    model.objects.all().order_by('?')[0]
    

    在此处阅读更多信息:https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by

    编辑:lazerscience 的回答确实更快,如图here

    【讨论】:

    • 这也很慢,您可以在您提供的链接中阅读:Note: order_by('?') queries may be expensive and slow...
    【解决方案3】:

    我会做的略有不同。无论如何,查询集在 django 中都是惰性的。

    import random
    
    def get_my_random_object():
        object = random.choice(model.objects.all())
        return object
    

    https://docs.djangoproject.com/en/dev/topics/db/queries/#querysets-are-lazy https://docs.djangoproject.com/en/dev/ref/models/querysets/#when-querysets-are-evaluated

    【讨论】:

    • random.choice() 调用len(queryset)(如random.py 所示)。这将评估整个查询集并将其拉入内存,然后再选择单个元素。
    猜你喜欢
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多