Actualmente estoy escribiendo una aplicación que permite almacenar imágenes y luego etiquetarlas. Estoy usando Python y el Peewee ORM (http://charlesleifer.com/docs/peewee/), que es muy similar al ORM de Django.Búsqueda de artículos en una relación muchos a muchos
Mi modelo de datos es el siguiente (simplificado):
class Image(BaseModel):
key = CharField()
class Tag(BaseModel):
tag = CharField()
class TagRelationship(BaseModel):
relImage = ForeignKeyField(Image)
relTag = ForeignKeyField(Tag)
Ahora, entiendo conceptualmente cómo consultar todas las imágenes que tienen un determinado conjunto de etiquetas:
SELECT Image.key
FROM Image
INNER JOIN TagRelationship
ON Image.ID = TagRelationship.ImageID
INNER JOIN Tag
ON TagRelationship.TagID = Tag.ID
WHERE Tag.tag
IN ('A' , 'B') -- list of multiple tags
GROUP BY Image.key
HAVING COUNT(*) = 2 -- where 2 == the number of tags specified, above
Sin embargo, también quiero poder hacer búsquedas más complejas. Específicamente, me gustaría poder especificar una lista de "todas las etiquetas", es decir, una imagen debe tener todas las etiquetas especificadas para ser devueltas, junto con una lista de "cualquiera" y una lista de "ninguna".
EDIT: Me gustaría aclarar esto un poco. Específicamente, la consulta anterior es una consulta al estilo de "todas las etiquetas". Devuelve imágenes que tienen todas las etiquetas dadas. Quiero poder especificar algo como: "Dame todas las imágenes que tengan las etiquetas (verde, montaña), cualquiera de las etiquetas (fondo, paisaje) pero no las etiquetas (digital, dibujo)".
Ahora, idealmente, me gustaría que esto sea una consulta SQL, porque la paginación se vuelve muy fácil con LIMIT y OFFSET. De hecho, tengo una implementación en funcionamiento por la cual solo cargo todo en los conjuntos de Python y luego uso los diversos operadores de intersección. Lo que me pregunto es si hay un método para hacer esto de una vez.
Además, para los interesados, he escrito el autor de Peewee acerca de cómo representar la consulta anterior usando Peewee, y él respondió con la siguiente solución:
Image.select(['key']).group_by('key').join(TagRelationship).join(Tag).where(tag__in=['tag1', 'tag2']).having('count(*) = 2')
O, de forma alternativa, una versión más corta :
Image.filter(tagrelationship_set__relTag__tag__in=['tag1', 'tag2']).group_by(Image).having('count(*) = 2')
Gracias de antemano por su tiempo.
Si entiendo correctamente, usted tiene la respuesta que necesita en el código peewee, pero ¿desea saber cómo hacer lo mismo en sql recto? –
puede explicar la parte "Sin embargo, también deseo poder realizar búsquedas más complejas. Específicamente, me gustaría poder especificar una lista de" todas las etiquetas ", es decir, una imagen debe tener todas las especificaciones etiquetas que se devolverán, junto con una lista de "cualquiera" y una lista de "ninguno". " – naresh
@naresh Específicamente, la consulta anterior es una consulta al estilo de "todas las etiquetas". Devuelve imágenes que tienen todas las etiquetas dadas. Quiero poder especificar algo como: "Dame todas las imágenes que tengan las etiquetas (verde, montaña), cualquiera de las etiquetas (fondo, paisaje) pero no las etiquetas (digital, dibujo)". Háganme saber si eso no está claro. –