В настоящее время я пишу приложение, которое позволяет хранить изображения, а затем помечать эти изображения. Я использую Python и Peewee ORM (http://charlesleifer.com/docs/peewee/), который очень похож на ORM Django.Поиск элементов в отношениях «многие ко многим»
Моя модель данных выглядит следующим образом (упрощенно):
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».
EDIT: Я хотел бы пояснить это немного. В частности, вышеуказанный запрос является запросом «все теги». Он возвращает изображения, у которых есть все теги. Я хочу иметь возможность указать что-то вроде: «Дайте мне все изображения, в которых есть теги (зеленый, горный), любой из тегов (фон, пейзаж), но не теги (цифровые, чертежи)».
Теперь, в идеале, я хотел бы, чтобы это был один запрос 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')
Заранее благодарим за ваше время.
Если я правильно понимаю, у вас есть ответ, который вам нужен в коде peewee, но вы хотите знать, как сделать то же самое в прямом sql? –
вы можете объяснить часть «Однако я также хочу иметь возможность выполнять более сложные поиски. В частности, я хотел бы указать список« всех тегов »- то есть изображение должно иметь все указанные теги, которые будут возвращены, вместе со списком «any» и списком «none». » – naresh
@naresh В частности, приведенный выше запрос является запросом «все теги». Он возвращает изображения, у которых есть все теги. Я хочу иметь возможность указать что-то вроде: «Дайте мне все изображения, у которых есть теги (зеленый, горный), любой из тегов (фон, пейзаж), но не теги (цифровые, чертежи)». Пожалуйста, дайте мне знать, если это не ясно. –