Commits

Anonymous committed efcaeb8

very basic Riak Search usage

latest version of each article is tossed to Search, and requests for
pages that don't exist ask Search to look for pages containing the
words of the page title requested

  • Participants
  • Parent commits a1a1de7

Comments (0)

Files changed (5)

File apps/wriaki/src/wiki_resource.erl

     to_html(RD, ACtx).
 
 render_404(RD, Ctx) ->
+    Search = mochiweb_util:unquote(base64url:decode_to_string(search_path(RD))),
+    Results = search(Ctx#ctx.client, Search),
     {ok, C} = error_404_dtl:render([{req, wrq_dtl_helper:new(RD)},
-                                    {search, mochiweb_util:unquote(base64url:decode_to_string(search_path(RD)))}]),
+                                    {search, Search},
+                                    {results, Results}]),
     {C, RD, Ctx}.
+
+-define(SEARCH_FUN,
+        iolist_to_binary(
+          [<<"function(v) {\n">>,
+           <<"return [v.key];\n">>,
+           <<"}">>])).
+
+search(Client, RawSearch) ->
+    case wriaki:search_enabled() of
+        true ->
+            Search = sanitize_search(RawSearch),
+            {ok, RawResults} =
+                wrc:mapred(Client,
+                           {modfun, riak_search, mapred_search,
+                            [<<"article">>,
+                             iolist_to_binary([<<"text:">>, Search])]},
+                           [{map, {jsanon, ?SEARCH_FUN}, <<>>, true}]),
+            case RawResults of
+                [{0, RawKeys}] ->
+                    [ [{url, base64url:decode(R)},
+                       {title, mochiweb_util:unquote(base64url:decode(R))}]
+                      || R <- RawKeys ];
+                _ ->
+                    []
+            end;
+        false ->
+            []
+    end.
+
+sanitize_search(RawSearch) ->
+    [ whitespace_search_operator(C) || C <- RawSearch ].
+
+whitespace_search_operator(C) ->
+    case is_search_operator(C) of
+        true -> 32; % space
+        false -> C
+    end.
+
+-define(SEARCH_OPERATORS,
+        [
+         $:,
+         $(,
+           $),
+         ${,
+           $},
+         $[,
+           $],
+         $+,
+         $-,
+         $!,
+         $&,
+         $|,
+         $^,
+         $~,
+         $*,
+         $?,
+         34  % double quote "
+        ]).
+
+is_search_operator(C) ->
+    lists:member(C, ?SEARCH_OPERATORS).

File apps/wriaki/src/wriaki.erl

 -module(wriaki).
 
 -export([set_bucket_props/0,
+         search_enabled/0,
          get_app_env/2]).
 
 -include_lib("wriaki.hrl").
 
 set_bucket_props() ->
     {ok, Client} = wrc:connect(),
-    ok = wrc:set_bucket(Client, ?B_ARTICLE, [{allow_mult, true}]),
+    ok = wrc:set_bucket(Client, ?B_ARTICLE,
+                        [{allow_mult, true}|search_hook()]),
     ok = wrc:set_bucket(Client, ?B_HISTORY, [{allow_mult, true}]).
 
+search_hook() ->
+    case search_enabled() of
+        true ->
+            [{precommit, [{struct,[{<<"mod">>,<<"riak_search_kv_hook">>},
+                                   {<<"fun">>,<<"precommit">>}]}]}];
+        _ ->
+            []
+    end.
+
+search_enabled() ->
+    get_app_env(search_enabled, false) == true.
+
 get_app_env(Env, Default) ->
     case application:get_env(wriaki, Env) of
         {ok, Val} -> Val;

File apps/wriaki/templates/base.dtl

           <span class="wikiletter">i</span>
         </a>
         &nbsp;&nbsp;
-        <input id="searchtext" value="{% if search %}{{ search }}{% endif %}" />
+        <input id="searchtext" value="{% if search %}{{ search|escape }}{% endif %}" />
         <button id="searchbutton">go</button>
       </div>
       <div id="welcome">

File apps/wriaki/templates/error_404.dtl

   <div class="notfound">
     <h2>No page was found for &quot;{{ search|escape }}&quot;</h2>
     <p>Would you like to <a href="/wiki/{{ search|escape }}?edit">create it</a>?</p>
+    {% if results %}
+    <h2>Perhaps you were looking for one of these pages?</h2>
+    <ul>
+      {% for result in results %}
+      <li><a href="/wiki/{{result.url}}">{{result.title|escape}}</li>
+      {% endfor %}
+    </ul>
+    {% endif%}
   </div>
 {% endblock %}

File rel/overlay/etc/app.config

            {riak, {pb, {"127.0.0.1", 8087}}},
 %           {riak, {http, {"127.0.0.1", 8098, "riak"}}},
 
+           %% Search functionality
+%           {search_enabled, true},
+
            %% Web interface settings
            %% web_ip: what IP to listen on (0.0.0.0 = listen on all)
            {web_ip, "0.0.0.0"},