2017-08-07 73 views
0

我試圖運行一個查詢,根據字典列表篩選結果。針對字典列表的Sqlalchemy查詢

讓我們更清晰......

我有一個表格標題,每個標題有一個版本字段

class Heading(Base): 
    id = Column(Integer, primary_key=True) 
    name = Column(String(50), nullable=False) 
    version = Column(Integer) 

在另一方面,我有字典,看起來像這樣的列表(JSON格式化):

"headings": [ 
    { 
     "id": 1, 
     "version": 1 
    }, 
    { 
     "id": 2, 
     "version": 1 
    } 
] 

我想執行上排除行,其中在數據庫中的版本是等於(JSON)列表中選擇版本的標題表的查詢。

我試圖執行是這樣的:

res = Heading.query.filter(~Heading.id.in_([d['id'] for d in headings if d['version'] == Heading.version])).all() 

與數據庫看起來像這樣(JSON再次格式化,不好意思):

[ 
{ 
    "id": 1, 
    "name": "Heading1", 
    "version": 2, 
}, 
{ 
    "id": 2, 
    "name": "Heading2", 
    "version": 1, 
} 
] 

但也無妨返回Heading2行。基本上,我希望查詢返回在Json中未定義的所有行以及在數據庫中具有較新版本的行。

我不知道我的問題是否足夠清楚。 也許這是不正確的方法,請讓我知道提前

感謝所有幫助

編輯: 生成的原始SQL是這樣:

SELECT heading.id, heading.name, heading.version 
FROM heading 
WHERE heading.id = heading.id 

因此,有一個sqlalchemy查詢明顯的問題,但我不知道什麼...

我認爲它來自部分

if d['version'] == Heading.version 

但我不知道該如何重新制定這一條件的其他地方查詢

+0

你可以發佈原始SQL查詢嗎? –

回答

1

正如你懷疑問題出在

[... for ... if d['version'] == Heading.version] 

雖然d['version'] == Heading.version產生SQL表達式對象,然後Python使用它的真值進行過濾:

In [9]: bool(headings[0]['version'] == Heading.version) 
Out[9]: False 

等等你的列表理解導致一個空的列表。一個Heading.id可能永遠不會在一個空列表,所以

~Heading.id.in_([]) 

會簡單地計算爲真:

In [10]: print(~Heading.id.in_([])) 
1 = 1 

鑑於您的數據庫支持composite IN queries的解決方案是對比(ID,版本)元組:

In [9]: from sqlalchemy import tuple_ 

In [10]: session.query(Heading).\ 
    ...:  filter(~tuple_(Heading.id, Heading.version).in_(
    ...:   [(d['id'], d['version']) for d in headings])).\ 
    ...:  all() 
Out[10]: [<__main__.Heading at 0x7f840cc8ae48>] 

In [11]: _[0].name 
Out[11]: 'Heading1' 
+0

非常感謝您的回答,這比我找到的解決方案更加優雅。肯定會重用這些複合IN查詢。 – CloC