以下是我的 Model 模型
class LocationModel(DataBase):
id: GUID = Column(GUID, primary_key=True, default=uuid.uuid4)
name: str = Column(String(length=32), unique=True, nullable=False)
member_come = relationship(
'MemberComeModel',
back_populates='location',
uselist=True,
cascade='all, delete',
passive_deletes=True
)
class MemberModel(DataBase):
id: GUID = Column(GUID, primary_key=True, default=uuid.uuid4)
name: str = Column(String(length=32), nullable=False)
image: str = Column(String(length=64), nullable=True)
class MemberComeModel(DataBase):
id: GUID = Column(GUID, primary_key=True, default=uuid.uuid4)
member_id = Column(GUID, ForeignKey('Member.id', ondelete='CASCADE'))
location_id = Column(GUID, ForeignKey('Location.id', ondelete='CASCADE'))
member = relationship('MemberModel', back_populates='member_come', uselist=False)
location = relationship('LocationModel', back_populates='member_come', uselist=False)
async def get_data():
query_set = await db.execute(select(MemberComeModel)).scalars().unique().all()
result = defaultdict(list)
for item in query_set: # type: MemberComeModel
result[item.location.id].append({
'name': item.member.name,
'image': item.member.image
})
print(result)
key 是 location id
value 是一個陣列
陣列裡面是 member name image 的值
{
UUID('bca3b662-a294-4ab5-b48c-2c0e26f0f132'): [{'name': '名字1', 'image': '/static/member/25d1d594-0c55-4c64-b39d-31efeb4729ff/image.png'}, {'name': '名字2', 'image': '/static/member/e50818f1-67e9-4edf-ab0e-9573ecae955e/image.jpg'}],
UUID('a87483a5-d6e1-4221-ae0c-317f7f5c2333'): [{'name': '名字3', 'image': '/static/member/a7a496fa-b8e5-44e0-a769-641289cd469b/image.jpg'}]
}
我覺得 orm 可以直接將我想要的理想結果拿出來,而不是我在特別寫用 for 迴圈
整理資料。
我覺得應該要用 group_by
還是 annotate
這類的解決問題。
但礙於我不熟 SQLalchemy 也不熟 SQL,只會用基本的用法。
想請教大家如何寫。
可使用下列查詢,輸出 Pandas DataFrame。
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
import sqlalchemy as db
import pandas as pd
from model import *
engine = db.create_engine('sqlite:///data.db', echo=True)
connection = engine.connect()
Base.metadata.create_all(engine)
query = db.select([MemberComeModel.id, MemberModel.name,
LocationModel.name]).join(MemberModel).join(LocationModel)
ResultSet = connection.execute(query).fetchall()
# convert to Data Frame
df = pd.DataFrame(ResultSet)
df.columns = ResultSet[0].keys()
print(df)
你已經寫好了
我覺得 orm 可以直接將我想要的結果拿出來,而不是我在用 for 迴圈去整理。
for item in query_set: # type: MemberComeModel
result[item.location.id].append({
'name': item.member.name,
'image': item.member.image
})
這段裡的 「query_set」 就已經是 orm 的結果了
而「拿出來」的方式就是你寫的
item.location.id
item.member.name
item.member.image
我的意思是我不想用 for 迴圈在整理資料,應該用 group_by 還是 annotate 就解決,query_set = orm 語法 = result。
我不明白你的「整理資料」指的是什麼
因為 query_set
的資料內容
和你「用 for 迴圈在整理資料」存進去的 result
一模一樣
就是我 quset_set 那行寫完就是我要的result了,不用寫 for。
quset_set 那行寫完就是我要的result
不用寫 for 就已經是了
query_set 和 result 的差別只有object 和 array 的差別
orm 就是 object
如果你就是需要/喜歡 array 的型式
就得把「orm 轉成 array 的型式」
或者「不要用 orm,直接從資料庫取得 array 型式的結果」
query_set 拿出來是 MemberCome Model 還不是我要的資料結構。
你是不是沒看到我 key 是 location.id? 這個是我從 MemberCome 拿出來的。
我貼的 Model 是我簡化的資料結構,我還有其他欄位,我並不需要其他欄位的資料。
這個 query_set 拿出來是這樣
[<database.models.member.MemberComeModel object at 0x000001D427DDCBB0>, <database.models.member.MemberComeModel object at 0x000001D427DE5A00>, <database.models.member.MemberComeModel object at 0x000001D427DE5B80>]
再退一步我把這個 query_set 轉成 dict 是這樣
[{'id': UUID('be5502cf-5023-4cab-b936-729acdbfa849'), 'member_id': UUID('25d1d594-0c55-4c64-b39d-31efeb4729ff'), 'location_id': UUID('bca3b662-a294-4ab5-b48c-2c0e26f0f132')}, {'id': UUID('c89c1a16-a8cd-4e56-83f1-28ef92980097'), 'member_id': UUID('e50818f1-67e9-4edf-ab0e-9573ecae955e'), 'location_id': UUID('bca3b662-a294-4ab5-b48c-2c0e26f0f132')}, {'id': UUID('2c2c1cfd-a08e-49b9-9eb7-e107ae31c678'), 'member_id': UUID('a7a496fa-b8e5-44e0-a769-641289cd469b'), 'location_id': UUID('a87483a5-d6e1-4221-ae0c-317f7f5c2333')}]
抱歉
是我看不懂你的 query_set, result 和 MemberComeModel
期待真正高手來解答吧
目前我用for就能解決了,只是我想知道sql語法是不是就能做好了,因為如果資料變很大量,sql做完給我比我用python速度還快。
我再看了一遍,終於懂了你的意思
我只找到這篇官網教學
試試看在 class MemberComeModel(DataBase) 裡加這段看看
__mapper_args__ = {
'include_properties' :['location.id', 'member.name','member.image']
}
我沒試過
所以不知道語法對不對
謝謝您提供的教學,我也學到了,但是這個是拿出我想要的 field,也就是 MemberComeModel 想要的 field,最終拿出來會像這樣,[{'member_id': member.id, 'member_name': member.name, 'member_image': member.image}],這樣還是要整理資料。