This is possible, but I'm guessing that in your Tags
table, you have one row for each tag per post. So one row containing the tag 'TermA' for post 1 and another record with the tag 'TermB', right?
The all words query (with +
) only returns rows where the searched field contains all the specified words. For the tags table, that is never the case.
One possible solution would be to store all tags in a single field in the posts table itself. Then it would be easy to do advanced matching on the tags as well.
Another possibility is to change the condition for tags altogether. That is, use an all
query for the text and an any
query for the tags. To do that, you'll have to modify the search query yourself, which can fortunately be as easy as removing the plusses from the query.
You can also query for an exact match, like this:
SELECT * FROM post p
WHERE
MATCH(p.text) AGAINST('TermA TermB' IN BOOLEAN MODE)
AND
/* Number of matching tags .. */
(SELECT COUNT(*) FROM tags t
WHERE
t.post = p.id
AND (t.tag in ('TermA', 'TermB')
= /* .. must be .. */
2 /* .. number of searched tags */ )
In this query, I count the number of matching tags. In this case I want it to be exactly 2, meaning that both tags match (provided that tags are unique per post). You could also check for >= 1 to see if any tags match.
But as you can see, this also requires parsing of the search string. You will have to remove the plusses (or even check their existence to understand whether you want 'any' or 'all'). And you will have to split it as well to get the number of searched words, and get the separate words themselves.
All in all, adding all tags to a 'tags' field in post
is the easiest way. Not ideal from a normalisation point of view, but that is managable, I think.