简体   繁体   English

Django - 从查询集中排除对象导致“表达式树太大”

[英]Django - excluding objects from queryset results in “expression tree is too large”

I'm working on a project that handles astronomical data (literally and figuratively) and have hit a roadblock when trying to exclude observations that require complex filtering.我正在处理一个处理天文数据(字面和比喻)的项目,并且在尝试排除需要复杂过滤的观测时遇到了障碍。

To be more specific, each Observation has one or more SpectralWindow s.更具体地说,每个Observation都有一个或多个SpectralWindow Users must be able to query observations by - among others - looking to their frequency coverage in relation to a band, a frequency range or an emission line.用户必须能够通过查看与频带、频率范围或发射线相关的频率覆盖范围来查询观测结果。 Regardless of the selected option, this coverage can be redshifted inside a specific z interval.无论选择何种选项,此覆盖范围都可以在特定的 z 区间内红移。

Since it's a bit hard to directly translate this to __lte -like selectors, I just filter the queryset and manually exclude observations that don't cover the calculated frequency range.由于直接将其转换为__lte的选择器有点困难,我只是过滤查询集并手动排除不涵盖计算频率范围的观察。 Something like this:像这样的东西:

for o in obs_result:
                covers = covers_ranges(z_bands, o) # <--- a more complex filtering solution
                if(not covers):
                    obs_result = obs_result.exclude(id=o.id) # <--- here's the problem!
                # update the min and max frequency values across the obs set
                else:
                    min_max = get_min_max_f(o)
                    min_freq = min(min_freq, min_max[0])
                    max_freq = max(max_freq, min_max[1])

The resulting query ends up like this:生成的查询结果如下:

SELECT ... FROM "common_observation" WHERE ("common_observation"."dec" >= 1.3365999999999998 AND "common_observation"."dec" <= 3.3366 AND "common_observation"."field_of_view" <= 300.0 AND "common_observation"."ra" >= 149.2375 AND "common_observation"."ra" <= 151.2375 AND NOT ("common_observation"."id" = 415) AND NOT ("common_observation"."id" = 416) AND NOT ("common_observation"."id" = 611) AND NOT ("common_observation"."id" = 612) AND NOT ("common_observation"."id" = 753) AND NOT ("common_observation"."id" = 758) AND NOT ("common_observation"."id" = 883) AND NOT ("common_observation"."id" = 884) AND NOT ("common_observation"."id" = 968) AND NOT ("common_observation"."id" = 984) AND NOT ("common_observation"."id" = 985) AND NOT ("common_observation"."id" = 995) AND NOT ("common_observation"."id" = 996) AND NOT ("common_observation"."id" = 997) AND NOT ("common_observation"."id" = 998) AND NOT ("common_observation"."id" = 999) AND NOT ("common_observation"."id" = 1000) AND NOT ("common_observation"."id" = 1001) AND NOT ("common_observation"."id" = 1002) AND NOT ("common_observation"."id" = 1052) AND NOT ("common_observation"."id" = 1053) AND NOT ("common_observation"."id" = 1086) AND NOT ("common_observation"."id" = 1087) AND NOT ("common_observation"."id" = 1088) AND NOT ("common_observation"."id" = 1089) AND NOT ("common_observation"."id" = 1090) AND NOT ("common_observation"."id" = 1091) AND NOT ("common_observation"."id" = 1092) AND NOT ("common_observation"."id" = 1093) AND NOT ("common_observation"."id" = 1099) AND NOT ("common_observation"."id" = 1100) AND NOT ("common_observation"."id" = 1111) AND NOT ("common_observation"."id" = 1154) AND NOT ("common_observation"."id" = 1156) AND NOT ("common_observation"."id" = 1157) AND NOT ("common_observation"."id" = 1158) AND NOT ("common_observation"."id" = 1159) AND NOT ("common_observation"."id" = 1204) AND NOT ("common_observation"."id" = 1205) AND NOT ...

...followed by a couple more hundreds of similar lines. ...随后是数百条类似的行。 When the list gets iterated over, this behemoth understandably throws an "expression tree is too large" error.当列表被迭代时,这个庞然大物会抛出“表达式树太大”错误,这是可以理解的。

I already tried to just evaluate the queryset to a list and filter from there, but it won't include related objects, meaning I can't look into related objects/fields ( Observation.SpectralWindow.start , for instance).我已经尝试将查询集评估为列表并从那里过滤,但它不会包含相关对象,这意味着我无法查看相关对象/字段(例如Observation.SpectralWindow.start )。

What's the protocol for these problems, if there are any?这些问题的协议是什么,如果有的话?

You may try to store ids in a list and then exclude all ids which are in the list, like this:您可以尝试将 id 存储在列表中,然后排除列表中的所有 id,如下所示:

exclude_ids = []
for o in obs_result:
                covers = covers_ranges(z_bands, o) # <--- a more complex filtering solution
                if(not covers):
                    #obs_result = obs_result.exclude(id=o.id) # <--- here's the problem!
                    exclude_ids.append(o.id)
                # update the min and max frequency values across the obs set
                else:
                    min_max = get_min_max_f(o)
                    min_freq = min(min_freq, min_max[0])
                    max_freq = max(max_freq, min_max[1])
obs_result = obs_result.exclude(id__in = exclude_ids)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM