我有几个看起来像这样的简单模型:
class StoreImage(Base):
imagepath = Column(Text, nullable=False)
store_id = Column(Integer, ForeignKey('store.id'), nullable=False)
store = relationship('Store')
class Store(Base):
status = Column(Enum('published', 'verify', 'no_position',
name='store_status'),
nullable=False, default='verify')
type = Column(Enum('physical', 'web', name='store_type'),
nullable=False, default='physical')
name = Column(Text, nullable=False)
street = Column(Text)
postal_code = Column(Text)
city = Column(Text)
country = Column(Text)
phone_number = Column(Text)
email = Column(Text)
website = Column(Text)
location = Column(Geometry(geometry_type='POINT', srid=4326))
is_flagship = Column(Boolean, default=False)
images = relationship(StoreImage)
现在我要做的就是这样查询:
q = Store.query.filter(Store.is_flagship == True).with_entities(
Store.id,
Store.status,
Store.slug,
Store.type,
Store.name,
Store.street,
Store.postal_code,
Store.city,
Store.country,
Store.phone_number,
Store.email,
Store.website,
func.ST_AsGeoJSON(Store.location).label('location'),
Store.images,
)
查询有效,但Store.images
只会为每一行返回True
。如何让它返回StoreImage
实例/ KeyedTuples的列表?
我想这样做主要是因为我还没有找到任何其他方法让Store.query
以GeoJSON格式返回该位置。
Store
个实例,并以某种方式添加location
GeoJSON,无论是在声明的模型上还是其他方式(如果可能)。不过不知道如何做到这一点。
答案 0 :(得分:1)
您当前的查询不仅会返回错误的值,而且实际上会返回错误的行数,因为它会执行两个表的笛卡尔积。
另外,我不会覆盖列名location
。因此,我将在下面的代码中使用geo_location
。
您是对的,为了预先加载图片,您必须查询整个Store
实例。例如,如下面的查询:
q = (session.query(Store)
.outerjoin(Store.images) # load images
.options(contains_eager(Store.images)) # tell SA that we hav loaded them so that it will not perform another query
.filter(Store.is_flagship == True)
).all()
为了将两者结合起来,您可以执行以下操作:
q = (session.query(Store, func.ST_AsGeoJSON(Store.location).label('geo_location'))
.outerjoin(Store.images) # load images
.options(contains_eager(Store.images)) # tell SA that we hav loaded them so that it will not perform another query
.filter(Store.is_flagship == True)
).all()
# patch values in the instances of Store:
for store, geo_location in q:
store.geo_location = geo_location
编辑-1:或者尝试使用column_property
class Store(...):
# ...
location_json = column_property(func.ST_AsGeoJSON(location).label('location_json'))
q = (session.query(Store).label('geo_location'))
.outerjoin(Store.images) # load images
.options(contains_eager(Store.images)) # tell SA that we hav loaded them so that it will not perform another query
.filter(Store.is_flagship == True)
).all()
for store in q:
print(q.location_json)
print(len(q.images))