Adding real time suggestions for search with ColdFusion, Solr, and jQuery

This post is more than 2 years old.

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.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Glyn Jackson posted on 11/17/2010 at 6:14 PM

Nice example, thanks! I know what I am doing tomorrow.

Comment 2 by Rick Smith posted on 11/17/2010 at 8:34 PM

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!

Comment 3 by Joel Stobart posted on 11/17/2010 at 8:58 PM

I'll bite; why can't you do what that blog recommended to the CF collections?

Comment 4 by Raymond Camden posted on 11/17/2010 at 9:05 PM

They manually created the index settings. We _can_ if we go to the XML but I wanted to stick to "vanilla" CF collections.

Comment 5 by Michael posted on 8/27/2013 at 1:32 PM

Hello Ray,

Your demo page is broken. The collection for "cfdocs" does not exist.

Just thought I'd let you know.

:)

Comment 6 by Michael posted on 8/27/2013 at 1:35 PM

ALSO...clicking on Rick Smith's name in the comment above, takes you to a porn website. Might wanna be careful there...

Comment 7 by Raymond Camden posted on 8/27/2013 at 2:40 PM

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.