【发布时间】:2017-03-27 20:56:28
【问题描述】:
我有以下型号:
class Member(models.Model):
ref = models.CharField(max_length=200)
# some other stuff
def __str__(self):
return self.ref
class Feature(models.Model):
feature_id = models.BigIntegerField(default=0)
members = models.ManyToManyField(Member)
# some other stuff
Member 基本上只是一个指向 Feature 的指针。所以假设我有特点:
- feature_id = 2, members = 1, 2
- feature_id = 4
- feature_id = 3
那么成员将是:
- id = 1,参考 = 4
- id = 2,参考 = 3
我想从“ok 成员”列表中查找包含一个或多个成员的所有功能。目前我的查询如下所示:
# ndtmp is a query set of member-less Features which Members can point to
sids = [str(i) for i in list(ndtmp.values('feature_id'))]
# now make a query set that contains all rels and ways with at least one member with an id in sids
okmems = Member.objects.filter(ref__in=sids)
relsways = Feature.geoobjects.filter(members__in=okmems)
# now combine with nodes
op = relsways | ndtmp
这非常慢,我什至不确定它是否有效。我尝试使用打印语句进行调试,只是为了确保实际上正在解析任何内容,我得到以下信息:
print(ndtmp.count())
>>> 12747
print(len(sids))
>>> 12747
print(okmems.count())
...然后代码只挂了几分钟,最终我退出了它。我认为我只是使查询过于复杂,但我不确定如何最好地简化它。我应该:
迁移功能以使用 CharField 而不是 BigIntegerField?我没有真正的理由使用 BigIntegerField,我这样做只是因为我在开始这个项目时正在遵循一个教程。我尝试了一个简单的迁移,只需在 models.py 中更改它,我在 PostgreSQL 的列中得到了一个“数字”值,格式为“十进制:(id)”,但可能有某种方法会迫使它只把 id 塞进一个字符串中。
使用我不知道的多对多字段的某些功能来更有效地检查匹配项
计算每个特征的边界框并将其存储在另一列中,这样我就不必每次查询数据库时都进行此计算(因此只需计算迁移时的单个固定成本 + 成本每当我添加新功能或修改现有功能时进行计算)?
还是别的什么?如果有帮助,这是我正在进行的 OpenStreetMap 相关项目的服务器端脚本,您可以看到正在进行的工作here。
编辑 - 我认为获得ndids 的更快方法是这样的:
ndids = ndtmp.values_list('feature_id', flat=True)
这有效,产生一组非空的 id。 不幸的是,我仍然不知道如何获得 okmems。我试过了:
okmems = Member.objects.filter(ref__in=str(ndids))
但它返回一个空的查询集。我可以通过以下测试确认参考点是正确的:
Member.objects.values('ref')[:1]
>>> [{'ref': '2286047272'}]
Feature.objects.filter(feature_id='2286047272').values('feature_id')[:1]
>>> [{'feature_id': '2286047272'}]
【问题讨论】:
标签: python django postgresql many-to-many postgis