9

I'm trying to figure out how, in a symfony 3.4 app, to retrieve (through a repository method, with a DQL request for example) entities depending on a value for a specific key in a "json" typed column. Saw there's some stuff possible with postgre but I didnt find anything with mariaDB

Let's say I get an entity Letter

with this property :

/**
 *
 * @ORM\Column(type="json")
 */
private $metadatas;

which contains, for example:

 {
    "key1": "value",
    "key2": "value"
 }

How can I, or, Is it possible to request my DB to get letters with a specific value for a specific key in metadatas column.

Something like that :

public function getByKeyValue($key, $value)
      {
          $em = $this->_em;
          $dql = "SELECT l FROM AppBundle:Letter l
                  WHERE l.metadatas->:key = :value
                  ";

          $query = $em->createQuery($dql);
          $query->setParameter('key', $key);
          $query->setParameter('value', $value);


          return $query->getResult();
      } 

some infos :

php7.1, mariadb 10.2+, doctrine/dbal ^2.6, doctrine orm ^2.5

Thanks a lot.

arnaudbey
  • 880
  • 1
  • 11
  • 19

1 Answers1

17

You can use ScientaNL/DoctrineJsonFunctions

Install it through composer by adding:

"scienta/doctrine-json-functions": "~4.0",

Register the json function that is needed in the doctrine configuration, in this case JSON_CONTAINS:

doctrine:
    orm:
        entity_managers:
            some_em: # usually also "default"
                dql:
                    string_functions:
                        JSON_CONTAINS: Scienta\DoctrineJsonFunctions\Query\AST\Functions\Mysql\JsonContains

In my case, I just added:

doctrine:
    orm:
         dql:
              string_functions:
                  JSON_CONTAINS: Scienta\DoctrineJsonFunctions\Query\AST\Functions\Mysql\JsonContains

Use it:

$queryBuilder = $this->getDoctrine()->getRepository('AppBundle:Letter')->createQueryBuilder('lt');
$queryBuilder
        ->where("JSON_CONTAINS(lt.metadatas, :mvalue, '$.key') = 1");

$queryBuilder->setParameter('mvalue', '"value"');
$query = $queryBuilder->getQuery();
return $query->getResult();

In dql, it should be something like:

$dql = "SELECT l FROM AppBundle:Letter l
              WHERE JSON_CONTAINS(lt.metadatas, :mvalue, '$.key') = 1
              ";

Note $.key is the json key to filter and mvalue should be included in its json encoded format, in this case with double quotes.

References:

MySql json-search-functions

romaricdrigon
  • 1,497
  • 12
  • 16
Jannes Botis
  • 11,154
  • 3
  • 21
  • 39
  • 2
    Historical note, as of 01/2019 the package was renamed to `scienta/doctrine-json-functions`, and the namespace was changed. Before it was called `syslogic/doctrine-json-functions`. – romaricdrigon Jan 31 '19 at 09:27
  • @Jannes Botis When the parameter is dynamic do I need to add double quotes such as `->setParameter('mvalue', '"'.$mvalue.'"')`? Thanks – StockBreak Jan 19 '23 at 14:01
  • I assume yes, but it is been too long since I done this, can you try it or post a new question? – Jannes Botis Jan 19 '23 at 21:36