先决条件:
Article
s 我的模型:
class Report(BaseModel):
ios_report = JSONField()
android_report = JSONField()
class Article(BaseModel):
internal_id = models.IntegerField(unique=True)
title = models.CharField(max_length=500)
short_title = models.CharField(max_length=500)
picture_url = models.URLField()
published_date = models.DateField()
clip_link = models.URLField()
reports = models.ManyToManyField(
"Report", through="ArticleInReport", related_name="articles"
)
class ArticleInReport(BaseModel):
article = models.ForeignKey("core.Article", on_delete=models.CASCADE, related_name='articleinreports')
report = models.ForeignKey("core.Report", on_delete=models.CASCADE, related_name='articleinreports')
ios_views = models.IntegerField()
android_views = models.IntegerField()
@property
def total_views(self):
return self.ios_views + self.android_views
一切始于以设置的时间间隔创建的Report
对象。该报告包含有关文章及其各自视图的数据。 Report
将与Article
到ArticleInReport
有关联,而Article
在导入报告时保留了Article
中的用户总数。
在我看来,我需要显示以下信息:
如果存在,则
Report
对象在 lastviews.py
中的观看次数。如果不存在,则为0。
我的reports_in_time_range = Report.objects.filter(created_date__range=[starting_range, right_now]).order_by('created_date')
last_report = reports_in_time_range.prefetch_related('articles').last()
unique_articles = Article.objects.filter(articleinreports__report__in=reports_in_time_range).distinct('id')
articles = Article.objects.filter(id__in=unique_articles).distinct('id').annotate(
total_views=Case(
When(id__in=last_report.articles.values_list('id', flat=True),
then=F('articleinreports__ios_views') + F('articleinreports__android_views')),
default=0, output_field=IntegerField(),
))
文件:
filter(id__in=unique_articles)
对我的思维过程的一些解释:首先,仅获取出现在时间范围内(ArticleInReport
)的相关报告中的文章,仅返回不同的文章。接下来,如果文章的ID(当然是通过ArticleInReport
出现在上次报告的文章列表中,请计算该Article
的iOS视图和Android视图。>
上面的注释适用于大多数 CREATE TABLE tweets (
id BIGINT,
created_at STRING,
source STRING,
favorited BOOLEAN,
retweeted_status STRUCT< text : STRING, `user` : STRUCT<screen_name : STRING,name : STRING>, retweet_count : INT>,
entities STRUCT< urls : ARRAY<STRUCT<expanded_url : STRING>>,
user_mentions : ARRAY<STRUCT<screen_name : STRING,name : STRING>>,
hashtags : ARRAY<STRUCT<text : STRING>>>,
text STRING,
`user` STRUCT< screen_name : STRING, name : STRING, friends_count : INT, followers_count : INT, statuses_count : INT, verified : BOOLEAN, utc_offset : INT, time_zone : STRING>,
in_reply_to_screen_name STRING
)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
Location '/user/flume/tweets/';
,但由于其他原因而失败,但没有明显的原因。我尝试了许多不同的方法,但似乎总是得到错误的结果。
答案 0 :(得分:2)
避免数据库命中非常重要,但不要以此为代价。我认为您应该将查询分为两个或多个查询。拆分查询将提高可读性,并可能提高性能(有时两个简单查询的运行速度比复杂查询快)。请记住,您具有dics,理解和itertools的全部功能,可以处理部分结果。
reports_in_time_range = ( Report
.objects
.filter(created_date__range=[starting_range, right_now])
.order_by('created_date'))
last_report = reports_in_time_range.prefetch_related('articles').last()
report_articles_ids = ( Article
.objects
.filter(articleinreports__report=last_report)
.values_list('id', flat=True)
.distinct())
report_articles = ( Article
.objects
.filter(id__in=report_articles_ids)
.annotate( total_views=Sum(
F('articleinreports__ios_views') +
F('articleinreports__android_views'),
output_field=IntegerField()
)))
other_articles = ( Article
.objects
.exclude(id__in=report_articles_ids)
.annotate( total_views=ExpressionWrapper(
Value(0),
output_field=IntegerField())
)))
articles = report_articles | other_articles
答案 1 :(得分:1)
我可以看到x = df[(df.OBJECTID == 4440) & (df.Landuse == 'Grass - Urban')]
want_area = x['Area'].sum() #returning the whole dataframe sum for that field!!
summed = x['Area'].sum()
ratio = round(want_area / summed, 2)
的问题,因为它不知道要使用哪个ArticleInReport。...因此它可能会为与每个Article相关的每个ArticleInReport创建重复项。如@daniherrera所建议,您可以首先获取所需的所有文章,然后从上一个报告中获取所有ArticleInReport,这将是3个查询。然后,您可以循环浏览Articles,如果有Article的ArticleInReport,则分配视图计数,如果没有-分配零。如果您不需要使用then=F('articleinreports__ios_views') + F('articleinreports__android_views')
进行任何其他的sql操作,则此方法将起作用。您可能想要在循环之前构建{Article.id:ArticleInReport}的字典,以便于查找。
另一种方法(如果需要某种过滤或排序或其他方法)是使用上次报告中的ArticleInReport的total_views
来为Article queryset添加Subquery
注释。然后,当文章在上一个报告中未收到任何视图时,您可以使用total_views
运算符将Null替换为零。
P。 S.我认为Coalesce
是无用的,因为无论如何您都使用values_list。
P. P. S也不需要对unique_articles和article进行区分,因为__in查找将已经产生明显的结果
答案 2 :(得分:0)
您需要使用IN
来匹配唯一准确ID的方法所带来的问题将返回一个超出预期范围的边界,您可以直接使用反向名称来过滤商品对象,也可以过度使用unique < / p>
articles_with_views_in_range = (
Article.objects
.annotate(
total_views=Case(
When(articleinreports__range=(start_range, end_range),
then=F('articleinreports__ios_views') + F('articleinreports__android_views')),
default=0, output_field=IntegerField(),
)
).filter(total_views__gt=0)
)