2012-03-15 50 views
9

Giả sử chúng ta có một cơ sở dữ liệu PostgreSQL với hai bảng A, B.mối quan hệ SQLAlchemy với PostgreSQL ARRAY

 
table A columns: id, name 
table B columns: id, name, array_a 

Cột array_a trong bảng B có chứa một mảng chiều dài biến của id từ bảng A. Trong SQLAlchemy chúng ta có hai lớp mô hình những bảng biểu, nói lớp A và B.

sau đây hoạt động tốt để có được tất cả các đối tượng một được tham chiếu trong một đối tượng B:

session.query(A).join(B, A.id == func.any(B.array_a)).filter(B.id == <id>).all() 

Làm thế nào chúng ta có thể tạo ra một mối quan hệ trong B tham chiếu các đối tượng A tương ứng với mảng? Đã thử so sánh cột bằng cách sử dụng các số func.any ở trên nhưng nó phàn nàn rằng ANY(array_a) không phải là một cột trong mô hình. Chỉ định các điều kiện sơ cấp như trên dường như không cắt nó.

Trả lời

8

Mẫu chống này được gọi là "Jaywalking"; và hệ thống kiểu mạnh mẽ của PostgreSQL khiến nó rất hấp dẫn. bạn nên sử dụng bảng khác:

CREATE TABLE table_a (
    id SERIAL PRIMARY KEY, 
    name VARCHAR 
); 

CREATE TABLE table_b (
    id SERIAL PRIMARY KEY, 
    name VARCHAR 
); 

CREATE TABLE a_b (
    a_id INTEGER PRIMARY KEY REFERENCES table_a(id), 
    b_id INTEGER PRIMARY KEY REFERENCES table_b(id) 
) 

Đó là ánh xạ:

from sqlalchemy import * 
from sqlalchemy.dialects import postgresql 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import * 

Base = declarative_base() 

a_b_table = Table("a_b", Base.metadata, 
    Column("a_id", Integer, ForeignKey("table_a.id"), primary_key=True), 
    Column("b_id", Integer, ForeignKey("table_b.id"), primary_key=True)) 

class A(Base): 
    __tablename__ = "table_a" 
    id = Column(Integer, primary_key=True) 
    name = Column(String) 

class B(Base): 
    __tablename__ = "table_b" 
    id = Column(Integer, primary_key=True) 
    name = Column(String) 
    a_set = relationship(A, secondary=a_b_table, backref="b_set") 

dụ:

>>> print Query(A).filter(A.b_set.any(B.name == "foo")) 
SELECT table_a.id AS table_a_id, table_a.name AS table_a_name 
FROM table_a 
WHERE EXISTS (SELECT 1 
FROM a_b, table_b 
WHERE table_a.id = a_b.a_id AND table_b.id = a_b.b_id AND table_b.name = :name_1) 

Nếu bạn đang bị mắc kẹt với cột ARRAY, đặt cược tốt nhất của bạn là sử dụng một có thể lựa chọn thay thế mà "trông" giống như một bảng liên kết thích hợp.

from sqlalchemy import * 
from sqlalchemy.dialects import postgresql 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import * 

Base = declarative_base() 


class A(Base): 
    __tablename__ = "table_a" 
    id = Column(Integer, primary_key=True) 
    name = Column(String) 

class B(Base): 
    __tablename__ = "table_b" 
    id = Column(Integer, primary_key=True) 
    name = Column(String) 
    array_a = Column(postgresql.ARRAY(Integer)) 

a_b_selectable = select([func.unnest(B.array_a).label("a_id"), 
         B.id.label("b_id")]).alias() 

A.b_set = relationship(B, secondary=a_b_selectable, 
          primaryjoin=A.id == a_b_selectable.c.a_id, 
          secondaryjoin=a_b_selectable.c.b_id == B.id, 
          viewonly=True,) 

B.a_set = relationship(A, secondary=a_b_selectable, 
          primaryjoin=A.id == a_b_selectable.c.a_id, 
          secondaryjoin=a_b_selectable.c.b_id == B.id, 
          viewonly=True) 

mang đến cho bạn:

>>> print Query(A).filter(A.b_set.any(B.name == "foo")) 
SELECT table_a.id AS table_a_id, table_a.name AS table_a_name 
FROM table_a 
WHERE EXISTS (SELECT 1 
FROM (SELECT unnest(table_b.array_a) AS a_id, table_b.id AS b_id 
FROM table_b) AS anon_1, table_b 
WHERE table_a.id = anon_1.a_id AND anon_1.b_id = table_b.id AND table_b.name = :name_1) 

Và rõ ràng, vì không có bảng thực đó, viewonly=True là cần thiết và bạn không thể có được sự thoải mái, tốt lành objecty động bạn sẽ nếu bạn đã tránh Ði Ẩu .

+1

Tôi nghĩ 'mối quan hệ 'là một bí danh không được dùng nữa cho' mối quan hệ' kể từ một vài phiên bản. – ThiefMaster

+0

@ThiefMaster: bạn chính xác, cố định; tốt đẹp bắt – SingleNegationElimination

+0

Có thể lựa chọn làm những gì chúng ta cần, có. –

Các vấn đề liên quan