设计问题:概述页面的低负载数据聚合

时间:2019-05-08 06:35:34

标签: django postgresql

在这种情况下,最好的方法是在数据库或应用程序服务器上实现低负载:

比方说,我想构建一个Web应用程序,为每个用户提供一个概述页面。概述页面以汇总形式为每个用户显示用户的数据。例如,如果它是一个图书馆应用程序,它将显示用户总共访问了图书馆多少次,他总共阅读了多少本书,总共延迟交付了多少本书,在建筑物中花费了多少分钟。每次用户访问概述页面时,都应显示最新值。当用户与网站互动时,数字会发生变化。

我可以做的是为每个概述页面刷新在数据库中进行多次计数。但这会很昂贵。

views.py

def overview(request, userID):
    booksCount = Book.objects.count()
    booksReadCount = Book.objects.filter(UserID=userID, Status='read').count()
    # ... many more, same way
    libraryVisitedCount = LibraryVisits.objects.filter(UserID=userID).count()
    # many counts like these on different tables for the user

    data = {
        "booksCount" : booksCount,
        "booksReadCount" : booksReadCount,
        # ... many more
        "libraryVisitedCount" : libraryVisitedCount
    }

    render(..., context=data)

我以为我可以将JSON对象以及将在概述页面上显示的数据存储在数据库表中,并且每次站点上发生影响对象计数的事件时,我都会更新JSON。

或者我可以使用父视图,但是要刷新它,我每次都必须重新计算所有用户的所有数据,对吗?

还有其他想法吗?我正在使用django webframework和postgres数据库。

TL; DR:我想知道是否有比每次在数据库中多次计数更好的接收计数的方法?

谢谢。

1 个答案:

答案 0 :(得分:0)

可以说,在 .top2 { display: block; /* example width - can use '%' as well */ width: 300px; } .wrapper2 { position: relative; padding-bottom: 56.25%; height: 0; } video { position: absolute; top: 0; left: 0; width:100%; height: 100%; } Book等模型中,有related_name的用户模型的ForeignKey是这样的:

LibraryVisit

然后您可以像这样使用annotationconditional expression

class Book(models.Model):
    UserID = models.ForeignKey(User, related_name='books', on_delete=DO_NOTHING)

class LibraryVisit(models.Model):
    UserID = models.ForeignKey(User, related_name='library_visit', on_delete=DO_NOTHING)

并在模板中渲染计数,如下所示:

from django.db.models import Case, IntegerField, Sum, When

def overview(request, userID):
    users = User.objects.filter(pk=userId)
    users = users.annotate(
            booksReadCount=Sum(
                Case(
                    When(book__Status='read', then=1), 
                    output_field=IntegerField()
                )
            )
        ).annotate(library_visited_count=Count('library_visit'))
    # FYI: please use snake_case when defining object attribute(like model fields) as per PEP-8 style guide
    data = {
        "user_object" : users.first(),  # taking first item of the User queryset. Also DB is hit once in this step
        "booksCount" : Book.objects.count()
    }
    # access counts in view like this:
    # user.book_read_count
    # user.library_visited_count
    return render(..., context=data)

    # bold marked words are related_name