This week I read an interesting article on Solr and autocomplete. It got me thinking about similar behavior with Solr under ColdFusion. Without going into too much detail, a real autocomplete wasn't feasible with the Solr collections ColdFusion creates, but we could do something similar. Instead of providing a list of auto complete options on your search, I'm going to use Ajax to provide a suggestion based on what you type. Here is what I came up with.
First, I created a simple form:
<form method="post">
<cfoutput><input type="text" name="search" id="search" value="#htmlEditFormat(form.search)#"></cfoutput>
<input type="submit" value="Search"><br/>
<span id="suggestion"></span>
</form>
Everything above should make sense except perhaps for the span. The span is an empty place to put my suggestion when it is returned. Below the form I had a simple place to display the results.
<cfif len(form.search)>
<cfsearch collection="cfdocs" criteria="#form.search#" name="results" maxrows="10">
<cfdump var="#results#">
</cfif>
Now let's look at the jQuery. Back on the top of my document I've got this:
$(document).ready(function() {
$("#search").keyup(function() {
var current = $(this).val();
$.getJSON("search.cfc?method=getsuggestion&returnformat=json", {"search":current}, function(res,code) {
res = $.trim(res);
if(res != '') $("#suggestion").html("Consider searching for <b>"+res+"</b>");
else $("#suggestion").html("");
});
});
})
As you type, I grab the current value of the search field. This gets passed to a CFC (displayed below). The CFC will return a suggestion or a blank string. If we actually get a suggestion we format the result and display it in the span. Pretty simple, right? Now let's look at the CFC.
<cfcomponent output="false">
<cffunction name="getSuggestion" access="remote" returnType="string" output="false">
<cfargument name="search" type="string" required="true">
<cfset var status = "">
<cfset var results = "">
<cfsearch collection="cfdocs" criteria="#arguments.search#" maxrows="1" status="status"
suggestions="always" name="results">
<cfif len(trim(status.collatedresult))>
<cfreturn trim(status.collatedresult)>
<cfelse>
<cfreturn "">
</cfif>
</cffunction>
</cfcomponent>
All my component does is handle suggestions. I'd probably have the real search in there as well so my form above could be simpler, but for now this is sufficient. To get a suggestion, I simply do my search, set suggestions="always", and minimize my actual results with maxrows="1". Suggestions are returned in the status key "collatedresult" and sometimes include a space. Therefore I do a trim before possibly returning it. And now that I've written this, I can further simplify my CFC by just returning the trimmed result like so:
<cffunction name="getSuggestion" access="remote" returnType="string" output="false">
<cfargument name="search" type="string" required="true">
<cfset var status = "">
<cfset var results = "">
<cfsearch collection="cfdocs" criteria="#arguments.search#" maxrows="1" status="status"
suggestions="always" name="results">
<cfreturn trim(status.collatedresult)>
</cffunction>
You can see a demo of this by clicking the big button below. Useful? Suggestion - try typing 'cfcd' as it triggers a good suggestion. My search data is the CFML reference - not the complete doc set.
Sorry - this demo is no longer available online.
Archived Comments
Nice example, thanks! I know what I am doing tomorrow.
Very secksy! This is much better than the one I did with cfinput autosuggest, which was nifty, but not at all accurate. I was debating whether it would go realtime or not... I think your version here probably will be production caliber for my project(s). Thanks!
I'll bite; why can't you do what that blog recommended to the CF collections?
They manually created the index settings. We _can_ if we go to the XML but I wanted to stick to "vanilla" CF collections.
Hello Ray,
Your demo page is broken. The collection for "cfdocs" does not exist.
Just thought I'd let you know.
:)
ALSO...clicking on Rick Smith's name in the comment above, takes you to a porn website. Might wanna be careful there...
Thanks Michael. I removed the link from his comment. I don't believe I have the cfdocs installed anymore, so, the demo will need to stay dead.