[Catalyst-commits] r13805 -
trunk/examples/CatalystAdvent/root/2010/pen
dhoss at dev.catalyst.perl.org
dhoss at dev.catalyst.perl.org
Tue Dec 7 23:11:02 GMT 2010
Author: dhoss
Date: 2010-12-07 23:11:02 +0000 (Tue, 07 Dec 2010)
New Revision: 13805
Added:
trunk/examples/CatalystAdvent/root/2010/pen/data-searchengine.pod
Log:
added gphat's article
Added: trunk/examples/CatalystAdvent/root/2010/pen/data-searchengine.pod
===================================================================
--- trunk/examples/CatalystAdvent/root/2010/pen/data-searchengine.pod (rev 0)
+++ trunk/examples/CatalystAdvent/root/2010/pen/data-searchengine.pod 2010-12-07 23:11:02 UTC (rev 13805)
@@ -0,0 +1,129 @@
+=head1 Extensible Search with Data::SearchEngine
+
+=head2 Searching Is Important
+
+Search is the special sauce in the webscale sauce. Wait, that's not right.
+That's NoSQL. Search is the feature that makes the glorious expanse of the
+internet I<usable>. It's come to the point that typing a keyword into your
+search input box and pressing enter is faster than typing in a domain name.
+As such, search is an important feature in the microcosms we create as web
+developers. It's one of those things that we've likely all tried to implement
+to varying degrees in our careers. I've implemented quite a few search
+backends in my time. Those culminated in the use of
+L<Solr|http://lucene.apache.org/solr/> for work projects. Even with Solr in my
+toolbelt I occasionally find myself in need of a quick and dirty search that
+has no outside dependencies. This means I'll have to roll something with SQL
+and maybe
+L<Search::QueryParser|http://search.cpan.org/perldoc?Search::QueryParser>.
+Regardless of how I choose to implement the search in my web application I
+know that I'll abstract it using
+L<Data::SearchEngine|http://search.cpan.org/perldoc?Data::SearchEngine>.
+
+=head2 Goals
+
+Data::SearchEngine has two simple goals:
+
+=over 4
+
+=item Stay out of your way when I<implementing> a search.
+
+=item Provide a consistent API for I<using> search results.
+
+=back
+Accomplishing this goal requires some buy in on your part. It's a bit more
+expensive up front but I can tell you from personal experience that your
+search backend will grow and change in any reasonably web application. It's
+a good investment to take some time to design yours well.
+
+=head2 Implementation
+
+We'll throw together a dead simple search using
+L<DBIx::Class|http://search.cpan.org/perldoc?DBIx::Class> to illustrate how
+easy it is to build a new backend for Data::SearchEngine. Then we'll
+demonstrate using it in a web application so you can see the advantages of
+using an abstraction layer atop your search implementation.
+
+ package Data::SearchEngine::MySearch;
+ use Moose;
+ use Data::Page;
+
+ with 'Data::SearchEngine';
+
+ sub search {
+ my ($self, $query) = @_;
+
+ # Simple search!
+ my $rs = $resultset->search({ name => { 'like' => '%'.$query.'%' } });
+
+ # Make a results object from the rows we get back!
+ my $result = Data::SearchEngine::Results->new(
+ query => $query,
+ pager => Data::Page->new(
+ # You should really customize these based on the results of the
+ # query, but this will do for now
+ current_page => 1,
+ entries_per_page => 10,
+ total_entries => $rs->count,
+ )
+ );
+
+ # Add the "hits" to the results object! Note that the data goes into a
+ # 'values' hashref.
+ while(my $row = $rs->next) {
+ $result->add(Data::SearchEngine::Item->new(
+ values => {
+ name => $row->name,
+ description => $row->description
+ },
+ # You could customize this, if necessary!
+ score => 1
+ ));
+ }
+
+ # Give back the results object!
+ return $result;
+ }
+
+That's it! The code is really simple but the gist is: Get a resultset from
+DBIC and iterate over it, adding each row to the result!
+
+=head2 Use
+
+I'll admit: that wasn't super-exciting. The power comes in I<using> the
+search results in your application. Here's a simple TT example:
+
+ <ul>
+ [% FOREACH item = results.items %]
+ <li>[% item.get_value('name') %]</li>
+ [% END %]
+ </ul>
+
+The Item objects are stored in a simple list so that you can iterate over them.
+You get data from them using a C<get_value> method. This allows you to add
+arbitrary fields to fit your implementation.
+
+=head2 What's the Big Deal?
+
+The big deal is that if you want to add a new search feature, backend
+implementation or refactor your code you don't have to change anything in your
+interface. As the author of a Data::SearchEngine implementation you can even
+implement common features such as
+L<faceting|http://search.cpan.org/perldoc?Data::SearchEngine::Results::Faceted>
+or L<spellchecking|http://search.cpan.org/perldoc?Data::SearchEngine::Results::Spellcheck>
+and expose a common interface. When your needs outgrow your homegrown DBIC
+implementation you can move up to L<Solr|http://search.cpan.org/perldoc?Data::SearchEngine::Solr>
+and not have to change any code in your view!
+
+It should also be noted that – through the power of MooseX::Storage – the
+Results object is totally serializable! This means it's easy to cache!
+
+=head1 Summary
+
+Search implementations often start out simple and grow over time. Eventually
+this growth yields a messy pile of code that nobody remembers how to read any
+more. Data::SearchEngine can help you add search to your web application in a
+forward thinking way.
+
+=head2 AUTHOR
+gphat: Cory G Watson <gphat at cpan.org>
+
More information about the Catalyst-commits
mailing list