Reputation: 13418
I have a database with many-to-many relations on tag and person. I am in trouble when tried to search a person with multiple tags. I tried this but its fail:
$person = Doctrine_Query::create()
->from("Model_Person p")
->innerJoin("p.tags t")
->whereIn('t.id',$t)
->execute();
The above statement return all persons that have at least one of the tags in array $t, but I want only person that havel 'all' the tags on that array.
Anyone know how to achieve this ?
Thanks
Upvotes: 0
Views: 698
Reputation: 1656
After some time of research I found and adopt a pure SQL code which works exactly as I need. In my app rizidoro's person table is info table.
//$tagQueryString contains tags separated by space ex. "crisis usa"
$tagsArray = explode(' ', $tagQueryString);
$tagsArrayQuery = '"' . implode('","', $tagsArray) . '"';
//$tagsArrayQuery='"crisis","usa";
$fromQuery =
'
info i
INNER JOIN (SELECT it.info_id
FROM info_tag it
INNER JOIN info i
ON i.id = it.info_id
INNER JOIN tag t
ON t.id = it.tag_id
WHERE t.name IN (' . $tagsArrayQuery . ')
GROUP BY it.info_id
HAVING COUNT(it.info_id) = ' . count($tagsArray) . ') ii
ON i.id = ii.info_id';
$query = new Doctrine_RawSql();
$query->select('{i.*}');
$query->from($fromQuery);
$query->addComponent('i', 'Model_Info i');
//you can add offset and limit for pagination
$infos = $query->limit($resultsPerPage)
->offset($resultsPerPage * ($currentPage - 1))
->execute();
That is not elegant code, but works fine. I have no idea how to do it more "Doctrine-like". Here are other solutions to similar problems: http://www.sergiy.ca/how-to-write-many-to-many-search-queries-in-mysql-and-hibernate
Upvotes: 0
Reputation: 12998
This is because IN
returns all results with at least one match. Say if you have id IN(1,2,3)
it's the same as id = 1 OR id = 2 OR id = 3
.
To archieve your desired goal, use Doctrine's andWhere()
method with each value that is now in $t
e.g. [...]->andWhere('id = ?', 1)->andWhere('id = ?', 2)->[...]
Upvotes: 1