rizidoro
rizidoro

Reputation: 13418

how to search multiple tags in doctrine

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

Answers (2)

Tomasz Rozmus
Tomasz Rozmus

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

DrColossos
DrColossos

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

Related Questions