Reputation: 5222
I have a Django application with the following postgres db tables: Publication and Tag
Publication {
title
tags
}
Tag {
title
}
Tag and Publication have a many to many relationship.
What I want to do is do an and/or combo search: for example, let's say I have four tags: A, B, C, D. I want to find all publications that have an A OR B tag associated with it, AND a C OR D tag associated with it. For example, in a search field I might enter: (A || B) && (C || D). In other words, the results should yield publications that have at least one tag from each 'or' pair.
I'd like to be able to enter the tag titles and return the publication titles.
I tried doing this using a Django filter, and even asked this question yesterday: What is an Efficient Way to do an AND/OR Search Django-Postgres App? and finally realized that doing a raw sequel query was probably better. The only problem: I've never written a raw sequel statement.
I just spent the last couple of hours looking at this question: How to filter SQL results in a has-many-through relation, and trying to apply it to my circumstance, but I'm too much of a newbie to be able to do it.
Given my models, can anyone show me how to construct this query?
Upvotes: 4
Views: 642
Reputation: 658392
Of course, you would have a table implementing the n:m relationship. Like
publication_tag {
publication_id
tag_id
}
Then your query could look like:
SELECT p.publication_id, p.publication
FROM publication p
WHERE EXISTS (SELECT 1 FROM publication_tag
WHERE publication_id = p.publication_id
AND tag_id IN ('A', 'B')
)
AND EXISTS (SELECT 1 FROM publication_tag
WHERE publication_id = p.publication_id
AND tag_id IN ('C', 'D')
)
This should be among the fastest possible solutions. You already found the go-to question with a lot more sample queries for relational division.
Upvotes: 4