Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

Adding site search

edited February 2013 in Framework

What's the best way to add a simple search to a site? I see the wiki page on templates mentions search/index but I'm not sure that's still included. There's an app that uses ElasticSearch or IndexTank -- is that the way to go? It seems like a lot of power for a simple site.

Comments

  • Quality of search results from a database are really poor, so IMO a usable search engine ought to be used even on small sites. But there are a couple good options if you don't want to host your own copy of ElasticSearch:

    • Install Elefant's search app and use a service like HoundSleuth, who offer a free tier with ample room for small sites.
    • Try Swiftype, who also have a free tier. They're the ones powering the elefantcms.com search :)
  • Hmm. I've had decent results with mysql fulltext search.

    Does swiftype index the forums? Searching google with site:elefantcms.com seems to give better results. Faster, too. I know it's not fair to compare to google, but frankly, I haven't been impressed with the search at elefantcms.com. I admit that I may not have given it a fair trial, but my initial impressions were that it was slow and not super helpful due to the apparent lack of forum results.

  • It should be indexing the forum as well (which was why I used it instead of Elefant's own search app). I have noticed it indexing RSS feeds from the forum which are kind of annoying in the search results. I'll have to play with it to see how I can improve the results...

  • For example, try a search for prettify. That thread has been up for a couple days, but no results are found.

  • I believe I've solved the RSS inclusion at least. We'll see once it updates its index.

  • edited March 2013

    I checked out elasticsearch -- it requires java, which seems to conflict with elefant's lightweightness and speed. I was planning to install this site on a low-end VPS; wasn't planning to install java there (not sure if I even can).

    So I'm trying your suggestion of HoundSleuth. However, I'm getting an error in the installer when I tell it to install https://github.com/jbroadway/search.git: PHP Fatal error: Call to a member function page() on a non-object in /path/to/apps/designer/handlers/installer.php on line 19

  • Haven't touched the search app in a while, so it may be doing something "the old way"... I'll have to test it tomorrow, off to play some dodgeball soon :D

  • Have fun!

    When you get back, tomorrow, next day, whenever -- I don't think it's the search app's fault -- it's happening with any app I try to install.

  • Looks like I introduced a small bug in the app installer in the last round of changes. The latest commit on Github should fix that now.

  • Still having trouble with the installer.

    Error in /path/to/apps/designer/lib/GithubInstaller.php on line 20: Invalid argument supplied for foreach()
    [01-Mar-2013 23:13:55 GMT] PHP Fatal error:  Uncaught exception 'ErrorException' with message 'Invalid argument supplied for foreach()' in /path/to/apps/designer/lib/GithubInstaller.php:20
    Stack trace:
    #0 /path/to/apps/designer/lib/GithubInstaller.php(20): Debugger::handle_error(2, 'Invalid argumen...', '/path/to/r...', 20, Array)
    #1 /path/to/apps/designer/handlers/installer.php(47): GithubInstaller::install('https://github....')
    #2 /path/to/lib/Form.php(248): Controller->{closure}(Object(Form))
    #3 /path/to/apps/designer/handlers/installer.php(78): Form->handle(Object(Closure))
    #4 /path/to/lib/Controller.php(462): require('/path/to/r...')
    #5 /path/to/index.php(150): Controller->h in /path/to/apps/designer/lib/GithubInstaller.php on line 20
    
  • Quick thing to check: Do you have the PHP CURL extension installed?

  • Yes -- it downloaded the files successfully.

  • Tried installing an app on my laptop -- worked fine. Must be something about the setup on my workstation.

  • Do they both have CURL or just the one? Either way, looks like it could use better error handling :)

  • Both. I tried again on the workstation and it worked fine. I think the issue may have been that there were files or something left over from the earlier failed install.

  • It's weird. Some files are empty, while others are there. I removed the folder and installed from the zip file and that's working better.

  • That is strange. I'll have to do more testing and improve the error checking too. Could be having issues with the Github API calls not always working.

  • I'm still unconvinced about there not being a need for a local search interface. For instance, in my listings app, if I want to let people search for properties between x and y dollars and in location z, how would I do that with e.g. houndsleuth?

  • I'm going to go ahead and build a simple search facility for the app. If I want to let them query multiple fields, is there a way to parse a $_GET string for the different variables? For instance, search?price_low=200000&price_high=400000&type=Home. Or should I do search/price_low/200000/price_high/400000/type/Home? Or just parse $_GET myself?

  • Those should all be available via $_GET['price_low'], $_GET['price_high'], and $_GET['type'].

    And there's definitely times when you need a roll-your-own search. It's a hard problem producing quality results for general text, but for limited data types a MySQL-based solution can definitely work well too.

    With the existing search app, you can add your custom results by creating hooks in your app when an item is added, updated, or deleted in your CRUD forms, then in the master conf/config.php just add these lines:

    myapp/add[] = search/add
    myapp/edit[] = search/add
    myapp/delete[] = search/delete
    

    The indexer doesn't do updates, so the add in the second line isn't a typo, it should do the right thing.

  • Thanks; I'm not sure I get the custom results/hooks thing, but I'll check it out and see if I can figure it out.

  • I'm trying sqlite fulltext search. It meant dropping my table and recreating it as a virtual table.

    It seems good enough. It's nice because you can search all columns at once. The only issue so far is that in the admin, $form->data = new properties\Properties ($_GET['id']) no longer works because the virtual table returns no results for id='8'; it has to be id=8.

  • That sounds pretty cool. I haven't played with SQLite's fulltext capabilities yet myself.

    And it looks like you should be able to get around the quoting of the 8 by the PDO parameter binding if you change the line to this:

    $form->data = new properties\Properties ((int) $_GET['id']);
    
  • No luck with (int). This is the workaround I'm using:

    $p = new properties\Properties;
    $p->where ('id='.Template::Sanitize ($_GET['id']));
    $property = $p->fetch();
    $form->data = $property[0]->orig();
    

    Unrelated: I ran into an issue when I uploaded to the server (CentOS 6) because it didn't support FTS4. Switching to FTS3 fixed it.

  • Hmm. My workaround doesn't work. When I try to edit a property, I get Fatal error: Call to undefined method stdClass::put(). If I take out the ->orig I don't get the error but the property isn't updated.

  • What does this code output for you?

    $property = new properties\Properties ((int) $_GET['id']);
    info ($property->orig ());
    

    If you see the database info in the output, then the database call worked. Calling ->orig() converts it to a regular StdClass object though, so you have to call ->put() on the $property object and not the object returned from ->orig().

    In your workaround, a cleaner version would be to do this:

    $property = properties\Properties::query ()
        ->where ('id', $_GET['id'])
        ->single ();
    $form->data = $property->orig ();
    

    The single() method grabs just one object instead of an array like fetch() does, and you don't need the Template::sanitize() in the where() if you pass the data as a separate parameter, which will use PDO's proper database escaping.

  • I changed to using an id of the form this-property-id, and now your original code works fine. I think there may be an issue with PDO and int values in sqlite fts tables, but my internet was down so I couldn't investigate. At this point, I don't want to change back to check, sorry! Maybe when this project is done and I have a little more time.

    Thanks for the explanation about single(), put(), orig(), etc. I think I'm starting to get it.

Sign In or Register to comment.