В настоящее время я пишу приложение, которое позволяет хранить изображения, а затем помечать эти изображения. Я использую Python и ORM Peewee (http://charlesleifer.com/docs/peewee/),, который очень похож на ORM Джанго.
Моя модель данных выглядит так (упрощенно):
class Image(BaseModel):
key = CharField()
class Tag(BaseModel):
tag = CharField()
class TagRelationship(BaseModel):
relImage = ForeignKeyField(Image)
relTag = ForeignKeyField(Tag)
Теперь я концептуально понимаю, как запрашивать все изображения с заданным набором тегов:
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
Однако я также хочу иметь возможность выполнять более сложные поиски. В частности, я хотел бы иметь возможность указать список «всех тегов» - то есть изображение должно иметь все указанные теги, которые должны быть возвращены, наряду со списком «any» и списком «none».
РЕДАКТИРОВАТЬ: Я хотел бы уточнить это немного. В частности, приведенный выше запрос является запросом в стиле «все теги». Возвращает изображения, которые имеют все заданные теги. Я хочу иметь возможность указать что-то вроде: «Дайте мне все изображения, которые имеют теги (зеленый, гора), любой из тегов (фон, пейзаж), но не теги (цифровой, рисунок)».
Теперь, в идеале, я бы хотел, чтобы это был один SQL-запрос, потому что тогда разбиение на страницы становится очень простым с LIMIT и OFFSET. На самом деле у меня работает реализация, в которой я просто загружаю все в наборы Python и затем использую различные операторы пересечения. Что мне интересно, так это если есть способ сделать все это сразу?
Кроме того, для тех, кто заинтересован, я написал автору Peewee о том, как представить вышеуказанный запрос, используя Peewee, и он ответил следующим решением:
Image.select(['key']).group_by('key').join(TagRelationship).join(Tag).where(tag__in=['tag1', 'tag2']).having('count(*) = 2')
Или, альтернативно, более короткая версия:
Image.filter(tagrelationship_set__relTag__tag__in=['tag1', 'tag2']).group_by(Image).having('count(*) = 2')
Заранее спасибо за ваше время.