Raymond Camden's Blog Rss

Transfer Query - From Phrase to AND Search

7

Posted in ColdFusion | Posted on 09-23-2008 | 2,176 views

Not sure if anyone will find this helpful, but here goes. A user reported some dissatisfaction with the search engine at CFLib. Specifically a search for FOO GOO would result in an exact phrase match on foo goo. It would not match a UDF named MyFooMilkshakeBetterThanGoo.

This was because my search did the rather simple %SEARCH% style match (ie, match the search term exactly, case insensntive). Here is the original Transfer code I used for the search:

view plain print about
1<cfsavecontent variable="sql">
2from udf.udf
3where (udf.udf.name like :search
4or udf.udf.shortdescription like :search
5or udf.udf.description like :search)
6and udf.udf.released = :active
7order by udf.udf.name asc
8</cfsavecontent>
9
10<cfset q = variables.transfer.createQuery(sql)>
11<cfset q.setParam("search", "%" & arguments.search & "%", "string")>
12<cfset q.setParam("active", true, "boolean")>
13<cfset q.setCacheEvaluation(true)>

Even if you don't know Transfer, this should be readable to you. I do a match on either name, shortdescription, or description. If you search for FOO, then basically it ends up being a search on %FOO%. Again though this kind of breaks down when you search for multiple words.

I wanted to keep things simple, so I decided that any multiword search would be an AND style search (ie, all the words must match), and I'd split on an empty space. I rewrote the TQL like so:

view plain print about
1<cfsavecontent variable="sql">
2from udf.udf
3where (
4    <cfloop index="idx" from="1" to="#arrayLen(words)#">
5    <cfoutput>
6    (udf.udf.name like :word#idx#
7    or udf.udf.shortdescription like :word#idx#
8    or udf.udf.description like :word#idx#
9    ) <cfif idx lt arrayLen(words)>and</cfif>
10    </cfoutput>
11    </cfloop>
12)
13and udf.udf.released = :active
14order by udf.udf.name asc
15</cfsavecontent>
16    
17<cfset q = variables.transfer.createQuery(sql)>
18<cfloop index="idx" from="1" to="#arrayLen(words)#">
19    <cfset q.setParam("word#idx#", "%" & words[idx] & "%", "string")>
20</cfloop>
21<cfset q.setParam("active", true, "boolean")>
22<cfset q.setCacheEvaluation(true)>

First off, the variables words comes from this change in the function header:

view plain print about
1<cfset var words = listToArray(arguments.search," ")>

So a search for FOO GOO results in words being equal to ["FOO","GOO"]. Notice then my loop over the array. I didn't use the new array style cfloop as I wanted a counter variable I could check to see if I needed an AND at the end of each block.

The next change was to have a dynamic set of setParams. This will replace word1, word2, etc, with the proper value from the array.

A good test for this is a search for "host url". Before the change it returned nothing. Now it matches getCurrentURL, getHostFromURL, and getHostFromURLJava.

Comments

[Add Comment] [Subscribe to Comments]

Great feature Ray, I'm not using transfer, but have wished a number of times that this feature existed on cflib.

Any chance of adding this type of functionality to the search on riaForge?
Absolutely. I'll be changing from client side ajax search, which worked great when we had < 200 projects, to a server side search (we now have 550+). It's "on the list", along with expanding the capabilities for submanagers. Which I got no feedback on from my users, so I hope someone is using it. ;)
John and I are using it... and it works great for what we need so far... thanks :)
Heh, glad someone is. ;) Well, as you know, it gives you very little power now. I'd like to finish that area first before going to search, but at the same time, search is a bit more public and would probably be used a lot more.
And what happened to author pages and author search?
Eh? You mean CFLib or RIAForge? I used to have author search on an 'advanced' search page. I could return that. I don't think I ever had an author 'page' though.
Probably getting to the point an author search could be really handy :)

[Add Comment] [Subscribe to Comments]