logo
Ask your Symfony questions! Pay money and get answers fast! (more info)

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.

$100
I need examples of search code for Symfony 1.0

I need code examples of search code. This is for Symfony 1.0. I have been writing a lot of LIKE statements, but I need something better than that. Any plugins suggestion welcome, but I'd really like to see actual samples of action code for handling stuff like multiple words, and how did folks handle weighting.

In general, how much do folks like to push these issue out to the database? How much do folks like to do using PHP?

My database is MySql, and in this case I do not mind dropping out of Propel, if Propel gets in the way of doing good searches.

This question has been answered.

marshall | 05/06/10 at 11:23am Edit


(16) Responses

See a threaded view of answers?

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

  • avatar
    Last edited:
    05/06/10
    11:31am
    LuĆ£ de Souza says:

    You can try sfLucene plugin, http://www.symfony-project.org/plugins/sfLucenePlugin

  • avatar
    Last edited:
    05/06/10
    12:01pm
    Martin Palacio says:

    Hi Marshall,

    you can give a look at the excellent Askeet tutorial (it's for sf 1.0)

    here you have a full example: http://www.symfony-project.org/askeet/1_0/en/21

    good luck!

    EDIT: as the tutorial says, you may consider to try the Lucene approach.
    This is a great tutorial on how to use it, however, is not available for sf 1.0:
    http://www.symfony-project.org/jobeet/1_2/Propel/en/17

    ...maybe you can adapt it to your needs.

    Moreover, looking at the date of this post, it seems to correspond to sf 1.0:
    http://spindrop.us/2006/08/25/using-zend-search-lucene-in-a-symfony-app/

    Remember, you can install the Lucene library directly from the Zend Framework, or by using the sfLucenePlugin. BTW the readme offers a good kickstart: http://www.symfony-project.org/plugins/sfLucenePlugin/0_1_6?tab=plugin_readme

    Previous versions of this answer: 05/06/10 at 12:01pm

  • avatar
    Last edited:
    05/09/10
    12:20pm
    Arturo Linares says:

    You could try concatenating all columns you want to look into, and then use LIKE in the criteria. Something like this:


    $term = 'test';
    $c = new Criteria();

    $c->add(
    'concat('
    . CommentPeer::TITLE . " , '|' ,"
    . CommentPeer::DESCRIPTIION . " , '|'"
    . '',
    'concat('
    . CommentPeer::TITLE . " , '|' ,"
    . CommentPeer::DESCRIPTIION . " , '|'"
    . ')'
    . ' LIKE \'%'.$term.'%\'',
    Criteria::CUSTOM);

    $rs = CommentPeer::doSelect($c);


    * I updated the criteria, I was doing it backwards.

    Previous versions of this answer: 05/06/10 at 11:44am | 05/06/10 at 12:21pm

  • avatar
    Last edited:
    05/09/10
    12:20pm
    Eduardo Raffoul says:

    Zend Lucene has a great tool to perform searchs.

    This is what i've done (based on Jobeet tutorial, and has worked great):

    In the peer method declare
    //lib/model/PersonPeer.php

    static public function getLuceneIndex()
    {
    ProjectConfiguration::registerZend();

    if (file_exists($index = self::getLuceneIndexFile()))
    {
    return Zend_Search_Lucene::open($index);
    }
    else
    {
    return Zend_Search_Lucene::create($index);
    }
    }


    static public function getLuceneIndexFile()
    {
    return sfConfig::get('sf_data_dir').'/person.'.sfConfig::get('sf_environment').'.index';
    }


    Each time you save/update/delete a record, must update
    //lib/model/Person.class.php
    public function save(PropelPDO $con = null)
    {
    $object = parent::save($con);

    $this->updateLuceneIndex();

    return $object;
    }


    Still in your model, if you delete a field, you have to delete it from your search results

    public function delete(PropelPDO $con = null)
    {
    $luceneIndex = PersonPeer::getLuceneIndex();

    foreach ($luceneIndex->find('pk:'.$this->getId()) as $occurrence)
    {
    $luceneIndex->delete($occurrence->id);
    }

    return parent::delete($con);
    }


    Inside your class, you have to define what is gonna be indexed

    public function updateLuceneIndex()
    {
    $luceneIndex = JobeetJobPeer::getLuceneIndex();

    // remove existing entries (according to the id)
    foreach ($luceneIndex->find('pk:'.$this->getId()) as $occurrence)
    {
    $luceneIndex->delete($occurrence->id);
    }

    $doc = new Zend_Search_Lucene_Document();

    // store job primary key to identify it in the search results
    $doc->addField(Zend_Search_Lucene_Field::Keyword('pk', $this->getId()));

    // Here you must add the fields you want to index
    $doc->addField(Zend_Search_Lucene_Field::UnStored('name', $this->getName(), 'utf-8'));
    $doc->addField(Zend_Search_Lucene_Field::UnStored('lastName', $this->getLastName(), 'utf-8'));
    $doc->addField(Zend_Search_Lucene_Field::UnStored('passport', $this->getPassport(),'utf-8));
    // For any other fields of your interest, have to do the same

    // add job to the index
    $luceneIndex->addDocument($doc);
    $luceneIndex->commit();
    }

    To implement the search, in your action


    class personActions extends sfActions
    {
    //........

    public function executeSearch(sfWebRequest $request)
    {
    if (!$query = $request->getParameter('query'))
    {
    return $this->forward('person', 'index');
    }

    $this->jobs = PersonPeer::getForLuceneQuery($query);
    }

    // .......

    }


    In your peer method, this is getForLucenQuery

    static public function getForLuceneQuery($query)
    {
    $occurrences = self::getLuceneIndex()->find($query);

    $pks = array();
    foreach ($occurrences as $occurrence)
    {
    $pks[] = $occurrence->pk;
    }

    $criteria = new Criteria();
    $criteria->add(self::ID, $pks, Criteria::IN);
    $criteria->setLimit(30);

    return self::doSelect($criteria);
    }


    And the rest is to implement the view that is just to show your results


    I didn't told you the most impotant yet! If you don't know how to install it. I see according to other answers that there is a plugin for zend lucene search. But, what i have done is this:
    Download the framework from http://framework.zend.com/download/latest
    I have it saved on /lib/vendor/Zend

    And in your config/ProjectConfiguration.class.php add this

    static protected $zendLoaded = false;

    static public function registerZend()
    {
    if (self::$zendLoaded)
    {
    return;
    }

    set_include_path(sfConfig::get('sf_lib_dir').'/vendor'.PATH_SEPARATOR.get_include_path());
    require_once(sfConfig::get('sf_lib_dir').'/vendor/Zend/Loader/Autoloader.php');
    Zend_Loader_Autoloader::getInstance();
    self::$zendLoaded = true;
    }


    The difference with the plugin solution is that you wont need to load the ProjectConfiguration::registerZend() method and i guess that the object Zend_Search_Lucene_Document may have another name according to symfony's name's structure

    ------ UPDATE -------
    The piece of code above doesn't applies to symfony 1.0 as Arturo Linares remarks on his answer. BTW, i was checking the sfLucenePlugin and i see that it's still on beta status and hasn't been updated since April 08. I've never used this plugin, so i can't recommend to use it or not, instead my advice would be (if you decide to go on this way) to look around what people say about it, just to be sure that it's safe to use it in a production environment.
    --------------------

    Previous versions of this answer: 05/06/10 at 11:47am | 05/06/10 at 11:48am | 05/06/10 at 11:57am | 05/06/10 at 12:37pm | 05/06/10 at 12:39pm | 05/06/10 at 3:28pm | 05/06/10 at 3:29pm

  • avatar
    Last edited:
    05/09/10
    12:20pm
    Ender Technology says:

    sfLucenePlugin is going to be your fastest and easiest route to improving the search in regards to speed, keywords, weighting and ranking.

    The sfLucenePlugin README and the included app should be plenty to get you started out on it. If you need to start tweaking it or customizing it, I suggest checking out the excellent docs at: http://framework.zend.com/manual/en/zend.search.lucene.html

    Beware of adding wildcards to both sides of your keywords because that can result in significant slowdown and usually doesn't give the correct results users are looking for anyways.

    Rob O.
    Ender Tech Corp.
    www.endertech.com

  • avatar
    Last edited:
    05/09/10
    12:20pm
    Jakub Zalas says:

    If you have a lot of data or need a serious, more advanced and sophisticated search engine than you should use Apache Solr. Solr is an extension for the original Lucene (the one written in java).

    If you don't need serious search option or don't work on a high traffic website than just go for Zend Lucene (PHP).

    With Solr Basically you push your search out of the database and PHP. Problem in your case would be that you're using no longer supported symfony version (you should think about the upgrade) and there's no plugin for it. However, you can handle it on your own or use existing PHP library. Maybe you could also adapt one of the existing plugins for newer symfony versions.

    To make your application working with Solr you need to configure it first. You need to tell Solr what is going to be indexed and how by preparing special xml file.

    Later you need to feed the index. Your data needs to be pushed to solr server.

    While searching you should connect to solr server. In response it gives you the list of ids which match the criteria. You can use these ids to get the full information out of the database and present it to the user.

    It's extremely fast.

    Read more about Solr features
    Solr and PHP
    Solr tutorial
    Enterprise search with PHP and Apache Solr



    Sphinx is an alternative and luckily for you there is a symfony 1.0 plugin: sfSphinxPlugin

    Sphinx might be a simpler solution to implement.

    Previous versions of this answer: 05/06/10 at 2:43pm | 05/06/10 at 2:44pm | 05/06/10 at 2:46pm

  • avatar
    Last edited:
    05/09/10
    12:20pm
    Bill Hunt says:

    Halfway between Lucene and LIKE, there's Full Text Search in MySQL. If you're looking for for something with more power and without having to implement a serious solution, it's the way to go. Here's the documentation. In summary, you add a new type of Index on the column or columns that you're going to be searching and then match text against them. It handles the tokenizing for you, and you can even get back a decimal value to tell you how close it matches. You use it like a standard where clause, there are a few examples here.

  • avatar
    Last edited:
    05/09/10
    12:20pm
    Dragos Mihai Rusu says:

    Another approach would be using Sphinx and sfSphinxPlugin.
    Basically it's another application that runs and collects data from MySQL ( an SQL query is built to index data you need ).
    It's very fast, and you can keep propel.
    EDIT: One of Sphinx's advantages would be to get search results by relevance. I know people who implemented Sphinx for this feature only.

    You will have to modify the application (search component): first query sphinx to get ids and afterwards query database to get data based on PK (which is pretty fast).
    EDIT: searching *word* - wildcards can be enabled also

    The bottleneck would be when you have a lot of updated information in each minute and you need all updates in search almost instantly. Solution to this would be implementing 2 merged indexes (1 large one, 1 daily) and run 2 crons: 1 daily at least accessed hours to update the large one, and one at 2-3-5 minutes which will only update info in the current day.

    I can provide more information (at no cost) ( dragos.rusu@bytex.ro ).



    Previous versions of this answer: 05/06/10 at 3:49pm | 05/06/10 at 3:49pm | 05/06/10 at 3:52pm | 05/06/10 at 3:58pm | 05/07/10 at 2:26pm | 05/07/10 at 2:27pm

  • avatar
    Last edited:
    05/07/10
    2:26am
    sandip limbachiya says:

    Hello


    You can define option in dropdown in template files and than selected value you can get into actions. than put below code in your action.

    $omCriteria = new Criteria();

    $this->ssSearchValue = trim($this->getRequestParameter('searchvalue' , ''));

    $this->ssSearchBy = strtoupper($this->getRequestParameter('searchby'));

    $omCriteria->add('CommunityPeer::'.$this->ssSearchBy,"%".$this->ssSearchValue."%",Criteria::LIKE);

    $rs = CommunityPeer::doSelect($omCriteria);


    I think, this would be helpful to you other below are another link which is also helpful please check below link.

    http://www.symfony-project.org/askeet/1_0/en/21


    Thanks
    Sandip Limbachiya







    Previous versions of this answer: 05/07/10 at 2:26am

  • avatar
    Last edited:
    05/06/10
    1:28pm
    Arturo Linares says:

    If you use Lucene Eduardo has a good mini tutorial here :)

    But in sf1.0 you doesn't have ProjectConfiguration class. To autoload Zend libraries you'll have to add this to your settings.yml


    .settings
    zend_lib_dir: %SF_LIB_DIR%
    autoloading_functions:
    - [sfZendFrameworkBridge, autoload]


    The dir structure in /lib would be:


    model/
    Zend/
    Loader/
    Loader.php
    Search/

  • avatar
    Last edited:
    05/06/10
    4:09pm
    Ender Technology says:

    I forgot to mention that sfLucenePlugin is going to be the most portable too. The Lucene indexer and query is all implemented in PHP with no further dependencies. Any other solution is going to require you to spend time compiling/installing server software or concerning yourself with MyISAM.

    However, being implemented in PHP this can also work against you if speed is really a concern but with sfLucene being easy to install, index, and test then it shouldn't be difficult to establish a benchmark to make decisions against.

  • avatar
    Last edited:
    05/09/10
    12:10pm
    marshall says:

    Looking around, I find out that other departments in my company are using Sphinx. But I am told it is too big for what we are trying to do.

  • avatar
    Last edited:
    05/09/10
    12:11pm
    marshall says:

    Dragos, thanks. I am just told we use Sphinx elsewhere in company. When the rest of the company switches to Symfony, it will be good to use the plugin.

  • avatar
    Last edited:
    05/09/10
    12:13pm
    marshall says:

    Thanks for the link to the examples. Very useful. We are going to do some of this.

  • avatar
    Last edited:
    05/09/10
    12:14pm
    marshall says:

    Arturo, thanks much. I think some combination of what you posted and what Bill Hunt posted is going to be our path.

  • avatar
    Last edited:
    05/09/10
    12:17pm
    marshall says:

    Eduardo, thanks. After some thought, we decided to postpone Lucene. We plan to implement this long-term, but in the short term we are going to work with MySql full text searches, as Bill Hunt suggested. It is faster to implement.

This question has expired.





Current status of this question: Completed



Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.