2014-05-15 6 views
1

J'ai trois tables: file, file_tag et tag.
Maintenant, je veux trouver tous les fichiers qui ont les étiquettes avec l'ID 1 et 3.sqlalchemy relation plusieurs-à-plusieurs (système de balises)

Table: file Table: file_tag Table: tag

class File_Tag(Base): 
    __tablename__ = 'file_tag' 

    id = Column(Integer, primary_key=True) 
    file_id = Column('file_id', Integer, ForeignKey('file.id')) 
    tag_id = Column('tag_id', Integer, ForeignKey('tag.id')) 


class File(Base): 
    __tablename__ = 'file' 

    id = Column(Integer, primary_key=True) 
    name = Column(String(255)) 
    tags = relationship('File_Tag') 

class Tag(Base): 
    __tablename__ = 'tag' 

    id = Column(Integer, primary_key=True) 
    name = Column(String(255)) 
    files = relationship('File_Tag') 

C'est ce que j'ai:

session.query(File).join(File.tags).filter(File_Tag.tag_id.in_([1, 3])) 

Le problème est qu'il me montre tous les fichiers avec l'étiquette 1 OU 3, je veux voir tous les fichiers avec l'étiquette 1 ET 3.

Le SQL Interroge il produit ressemble à ceci:

SELECT file.id AS file_id, 
    file.name  AS file_name, 
    file.sha1  AS file_sha1, 
    file.import_id AS file_import_id 
FROM file 
INNER JOIN file_tag 
ON file.id    = file_tag.file_id 
WHERE file_tag.tag_id IN (1, 3) 
GROUP BY file.id 

En conséquence, je reçois les fichiers 2, 3 et 4, mais je devrais obtenir des fichiers de 2 et 4.

Je ne veux pas utiliser subquerys si possible, j'entendu dire qu'ils sont lents;)

Répondre

0

S'il vous plaît, essayez ceci:

SELECT file.id AS file_id, 
    file.name  AS file_name, 
    file.sha1  AS file_sha1, 
    file.import_id AS file_import_id 
FROM file 
INNER JOIN file_tag 
ON file.id   = file_tag.file_id 
WHERE file_tag.tag_id =1 
AND file_tag.file_id IN 
    (SELECT file_id FROM file_tag WHERE tag_id=3 
) 
GROUP BY file.id; 

En outre, un sqlalchemy devrait être quelque chose comme:

subq=session.query(File_Tag).filter(File_Tag.tag_id=3); 
session.query(File).join(File.tags).filter((File_Tag.tag_id=1)&(File_Tag.file_id.in(subq))) 

Il contient une sous-requête, mais je pense qu'il n'est pas possible d'obtenir ce que vous voulez sans les utiliser.

+0

Cela fonctionne mais j'ai besoin du code sqlalchemy pour ça, s'il vous plait! – fnkr

+0

En outre, je n'ai jamais utilisé sqlalchemy auparavant, j'ai essayé de produire le bon pour vous. Pls, voir l'édition. – Guneli

+0

Je pense que 1 sous-requête par tag est ok mais pouvez-vous me dire d'automatiser ceci si j'ai un 'list()' tags (de 0 à x tags). Par exemple: 'requested_tags = list (1, 3, 10, 15, ...)'. – fnkr

Questions connexes