Search code examples
symfonydoctrine-ormlucenecouchdbdoctrine-odm

Use Like% in CouchDB Doctrine Symfony 2


I'm using this bundle and I wanto to find my element by %LIKE% mysql

My document is like this:

{
   "_id": "60a403542a2b7d44bf84ed569d1e6efe",
   "_rev": "1-9e1ed380dd91ac8c835ef0f8e152f0a8",
   "type": "mytype",
   "doctrine_metadata": {
       "indexes": [
           "name",
       ]
   },
   "name": "barfoo",

}

I want to Find all element that begin with barfo

I saw this link, but I don't know if this is a right Solution. How Can I do Like query in couchDb + symfony2 ?


Solution

  • There aren't %Like% in couchDb (1.6.1), but you can use startkey and endkey.

    You have to create a view like:

    function (doc) {
        if (doc.type = 'myType') {
            emit(doc.name, doc.name);
        }
    }
    

    with name for example people.

    For example and simplicity

    Designname = people
    viewname = people
    

    After that you can do This Curl

    curl -X GET 'http://localhost:5984/db/_design/people/_view/people?startkey="foo"&endkey="foo\ufff0"'
    

    In this way you can find all element that begin with foo.

    Why \ufff0 ? Check this link

    String Ranges

    If you need start and end keys that encompass every string with a given prefix, it is better to use a high value unicode character, than to use a 'ZZZZ' suffix.

    That is, rather than:

    startkey="abc"&endkey="abcZZZZZZZZZ" You should use:

    startkey="abc"&endkey="abc\ufff0"

    How Can you do this in Symfony ?

    If you want to create View by Symfony You can Create the view in yourapp/AppBundle/CouchDocument/View/PeopleView.php

    <?php
    
    namespace yourapp\AppBundle\CouchDocument\View;
    
    use Doctrine\CouchDB\View\DesignDocument;
    
    class PeopleView implements DesignDocument
    {
    
        public function getData()
        {
            $people = <<<'JS'
    function (doc) {
            if (doc.type = 'myType') {
                emit(doc.name, doc.name);
            }
        }
    JS;
    
            return array(
                'views' => array(
                    'people' => array(
                        'map' => $people,
                    ),
                )
            );
    
        }
    }
    

    and in your controller you can do something like this

    /**
     * @Route("/testPeople/{code}", name="test_people")
     * @Method({"GET"})
     * @Template("myAppBundle:People:test_query.html.twig")
     */
    public function testPeopleAction($code)
    {
    
        $dm = $this->container->get(
            'doctrine_couchdb.odm.default_document_manager'
        );
        $peopleView = new PeopleView();
        $client = $this->container->get('doctrine_couchdb.odm.default_document_manager');
        $view = $client->createDesignDocument('people', $peopleView);
    
        $relatedObjects = $dm->createNativeQuery('people', 'people')
            ->setStartKey($code)
            ->setEndKey($code . "\xEF\xBF\xB0")
            ->execute();
        $a = array();
        foreach ($relatedObjects as $doc) {
            $a[] = $doc['value'] //it is your results
        }
    
        return array(
            'results' => $a
        );
    }
    

    I saw the unitTest inside vendor/doctrine/couchdb/tests/Doctrine/Tests/CouchDB/CouchDBClientTest.php to find something to usefull

    I Don't Know if it is the best way, but for me it works :)