1

我想要做什么:计算最流行的搜索查询:过去一天、过去 30 天、过去 60 天、过去 90 天、每个日历月以及所有时间。

我的原始数据是一个带时间戳的搜索查询列表,我已经在为相关数据聚合运行每晚的 cron 作业,因此我想将此计算集成到其中。每天阅读每个查询都很好(据我所知,这是必要的),但对于其他时间段,这将是一个昂贵的计算,所以我正在寻找一种方法来使用我的预先计算的数据来保存时间。

我不想做的事情:提取该期间每一天的记录,对所有计数求和,对整个结果列表进行排序,然后取前 X 值。这将是低效的,尤其是对于“所有时间”列表。

我考虑使用堆和二叉树来保持实时排序和/或更快地访问数据,并行读取每个列表中的单词并将它们的值推送到具有各种约束和结束条件的堆中,但这总是会破坏查找时间或排序时间,我基本上回到看一切。

我还考虑过保持每个时间段的运行总数,加上最近的一天并减去最早的一天(在每个月的 1 日保存每月总计),但是我必须每天保存每个时间段的完整计数(而不仅仅是前 X),我仍在查看每日总数中的每条记录。

有什么方法可以更快地执行此操作,也许使用其他一些数据结构或我不知道的有趣的数学属性?此外,任何人都需要知道,这整个事情都存在于 Django 项目中。

4

3 回答 3

1

最简洁的答案是不。

不能保证去年前十名的歌曲曾经出现在每日前十名的名单中(很有可能,但不能保证)。

获得绝对确定的前十名的唯一方法是将指定时间段内的所有选票相加,然后选择前十名。

于 2012-07-03T19:23:42.540 回答
0

可以使用 Counter() 类,它是高性能容器数据类型的一部分。创建所有搜索的字典作为字典的键,并计算它们的频率。


cnt = Counter()
for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
    cnt[word] += 1
print cnt
Counter({'blue': 3, 'red': 2, 'green': 1})

于 2012-07-03T18:34:13.687 回答
0

我不确定它是否适合您正在做的事情,但如果数据是通过 Django 模型存储的,您可以利用聚合来在单个查询中获取信息。

鉴于:

class SearchQuery(models.Model):
    query = models.CharField()
    date = models.DateTimeField()

然后:

import datetime
from django.db.models import Count

today = datetime.date.today()
yesterday = today - datetime.timedelta(days=1)
days_ago_30 = today - datetime.timedelta(days=30)
...

top_yesterday = SearchQuery.objects.filter(date__range=(yesterday, today)).annotate(query_count=Count('query')).order_by('-query_count')

top_30_days = SearchQuery.objects.filter(date__range=(days_ago_30, today)).annotate(query_count=Count('query')).order_by('-query_count')

...

这是使用 Django 完成的最有效的方法,但不一定是有效的。但是,执行诸如添加索引之类的操作query会有很大帮助。

编辑

我突然想到,你最终会在列表中得到欺骗。您可以在事后技术上对列表进行重复数据删除,但如果您将 Django 1.4+ 和 PostgreSQL 作为数据库运行,则可以简单地附加.distinct('query')到这些查询集的末尾。

于 2012-07-03T19:47:10.813 回答