我有一个搜索页面,其中列出了以下方案。我被告知使用如此多的条件语句会降低性能,但我不知道是否有任何其他方法可以实现相同的目标。
页面顶部逻辑如下:
<!---DEFINE DEFAULT STATE--->
<cfparam name="variables.searchResponse" default="">
<!---CHECK TO SEE IF SEARCH A FORM WAS SUBMITTED AND EXECUTE SEARCH IF IT WAS--->
<cfif IsDefined("Form.simpleSearch") AND Len(Trim(Form.titleName)) LTE 2>
<cfset variables.searchResponse = "invalidString">
<cfelseif IsDefined("Form.simpleSearch") AND Len(Trim(Form.titleName)) GTE 3>
<cfinvoke component="gz.cfcomp.search" method="searchTitles" titleName="#Form.titleName#" genreID="" platformID="" returnvariable="searchResult">
<cfset variables.searchResponse = "hasResult">
</cfif>
<!---CHECK IF ADVANCED SEARCH FORM WAS SUBMITTED--->
<cfif IsDefined("Form.advancedSearch") AND (Len(Trim(Form.titleName)) LTE 2 AND Len(Form.genreID) IS 0 AND Len(Form.platformID) IS 0)>
<cfset variables.searchResponse = "invalidString">
<cfelseif IsDefined("Form.advancedSearch") AND variables.searchResponse IS NOT "invalidString">
<cfinvoke component="gz.cfcomp.search" method="searchTitles" returnvariable="searchResult" titleName="#Form.titleName#" genreID="#Form.genreID#" platformID="#Form.platformID#">
<cfset variables.searchResponse = "hasResult">
</cfif>
<!---CHECK IF ANY RECORDS WERE FOUND--->
<cfif IsDefined("variables.searchResult") AND searchResult.RecordCount IS 0>
<cfset variables.searchResponse = "noResult">
</cfif>
我正在使用searchResponse变量根据以下情况决定页面显示的内容:
<!---ALWAYS DISPLAY SIMPLE SEARCH BAR AS IT'S PART OF THE HEADER--->
<form name="simpleSearch" action="search.cfm" method="post">
<input type="hidden" name="simpleSearch" />
<input type="text" name="titleName" />
<input type="button" value="Search" onclick="form.submit()" />
</form>
<!---IF NO SEARCH WAS SUBMITTED DISPLAY DEFAULT FORM--->
<cfif searchResponse IS "">
<h1>Advanced Search</h1>
<!---DISPLAY FORM--->
<form name="advancedSearch" action="search.cfm" method="post">
<input type="hidden" name="advancedSearch" />
<input type="text" name="titleName" />
<input type="text" name="genreID" />
<input type="text" name="platformID" />
<input type="button" value="Search" onclick="form.submit()" />
</form>
</cfif>
<!---IF SEARCH IS BLANK OR LESS THAN 3 CHARACTERS DISPLAY ERROR MESSAGE--->
<cfif searchResponse IS "invalidString">
<cfoutput>
<h1>INVALID SEARCH</h1>
</cfoutput>
</cfif>
<!---IF SEARCH WAS MADE BUT NO RESULTS WERE FOUND--->
<cfif searchResponse IS "noResult">
<cfoutput>
<h1>NO RESULT FOUND</h1>
</cfoutput>
</cfif>
<!---IF SEARCH MADE AND RESULT WAS FOUND--->
<cfif searchResponse IS "hasResult">
<cfoutput>
<h1>Search Results</h1>
</cfoutput>
<cfoutput query="earchResult">
<!---DISPLAY QUERY DATA--->
</cfoutput>
</cfif>
我的逻辑是否a)效率不高,因为我的if语句/是否有更好的方法来做到这一点?并且b)你能看到我的代码可以破解的任何场景吗?我已经测试了它,但我一直无法找到任何问题。我无法衡量绩效。任何想法和想法将不胜感激。
这是我的功能,供参考:
<!---SEARCH--->
<cffunction name="searchTitles" hint="This functions searches for a title based on multiple categories" access="public" output="false">
<cfargument name="titleName" required="no" type="string" hint="Search by title">
<cfargument name="genreID" required="no" type="string" hint="Search by genre">
<cfargument name="platformID" required="no" type="string" hint="Search by platform">
<!--- DEFINE LOCAL VARIABLES - NOTE VARIABLE NAME IS QUERY NAME --->
<cfset var searchResult = "">
<!---GET RESULTS--->
<cfquery name="searchResult" datasource="myDSN">
SELECT
games.gameID,
games.gameReleaseDate AS rDate,
titles.titleName AS tName,
titles.titleShortDescription AS sDesc,
platforms.platformName AS pName,
genres.genreName AS gName
FROM
games
INNER JOIN titles ON titles.titleID = games.titleID
INNER JOIN platforms ON games.platformID = platforms.platformID
INNER JOIN genres ON games.genreID = genres.genreID
WHERE
0=0
<cfif ARGUMENTS.titleName IS NOT "">
AND titles.titleName LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#ARGUMENTS.titleName#%">
</cfif>
<cfif ARGUMENTS.genreID IS NOT "">
AND games.genreID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#ARGUMENTS.genreID#">
</cfif>
<cfif ARGUMENTS.platformID IS NOT "">
AND games.platformID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#ARGUMENTS.platformID#">
</cfif>
ORDER BY
rDate DESC,
tName;
</cfquery>
<cfreturn searchResult>
</cffunction>
非常感谢
答案 0 :(得分:1)
您是否考虑过使用全文搜索而不仅仅是标题,流派和平台等具体内容?全文比普通表查询快得多,代价是更多的磁盘空间使用,并允许对所有数据进行非常灵活的Google样式搜索。请看下面的链接。
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
也许如果你这样做,你可以通过用户输入实现全文搜索,因为它通过它自己的语法提供所有高级搜索表达式。通过这样做,您可能不需要根据他们搜索的内容来分支您的前端逻辑,这将使解决方案更清晰,更快。
答案 1 :(得分:1)
我认为只是一种偏好,但自谷歌问世以来,人们希望一个搜索框可以做任何事情。您可以通过测试输入并有条件地运行单独的查询并返回组合结果,直接从简单框中提供一些高级搜索功能。为了使结果更清晰,您可以使用Coldfusion或javascript突出显示匹配部分。
我也会初始化组件而不是多次使用cfinvoke,但我不确定这是一个要求还是一个偏好。
<!--- By setting a default, we don't have to test for this var's existence repeatedly --->
<cfparam name="form.simpleSearch" default="" />
<cfscript>
// Using cfscript for compactness in this little box, could use tag based cf also
// Init myComponent so that it's ready to receive searches
searcher = createObject('component','myComponent');
// init query results
simpleResult = queryNew("id");
genres = queryNew("id");
platforms = queryNew("id");
titles = queryNew("id");
// q: shorthand 'Query' var that's trimmed and prechecked for length
q = "";
if (len(trim(form.simpleSearch)) GTE 3) {
q = trim(form.simpleSearch);
}
// Run simple search - Should returns a query object regardless of result count
if (len(q) {
simpleResult = searcher.simpleSearch(q);
/* Not sure what the difference between this and simpleSearch() is unless
this only looks for exact matches, and simpleSearch() uses LIKE and %
wildcards for looser results. */
titles = searcher.titleSearch(q);
/* Conditionally run advanced searches
- assumes that genreID and platformID are numeric
- IF genreID and platformID are not numeric, you could use regex to test for their signature or just run them anyway knowing they wouldn't match in many cases. (BUT you must, must MUST use cfqueryparam if you attempt that)
- Requires that advancedSearch is split into three separate functions
- Alternately, the simpleSearch(q) or advancedSearch() could do this all internally
- All of these functions should return an empty query if no results are found
if (isNumeric(q)) {
genres = searcher.genreSearch(q);
platforms = searcher.platformSearch(q);
}
}
</cfscript>
...
<!---ALWAYS DISPLAY SIMPLE SEARCH BAR AS IT'S PART OF THE HEADER--->
<cfoutput>
<form action="#cgi.script_name#" method="post">
<input type="text" name="simpleSearch" value="#form.q#" />
<input type="submit" value="Search" name="submit" />
</form>
<cfif titles.recordcount>
<h3>Matching Titles</h3>
<cfloop query="titles">
..html to output the titles
</cfloop>
</cfif>
<cfif genres.recordcount>
<h3>Matching Genres</h3>
<cfloop query="genres">
..html to output the genres
</cfloop>
</cfif>
<cfif platforms.recordcount>
<h3>Matching Platforms</h3>
<cfloop query="platforms">
..html to output the platforms
</cfloop>
</cfif>
<cfif simpleResult.recordcount>
<h3>Results</h3>
<cfloop query="simpleResult">
..html to output the simpleResult
</cfloop>
</cfif>
</cfouput>
当然,有许多不同的方法可以做到这一点。这只是降低简单搜索与高级搜索复杂性的一种方法。只有匹配时才会显示高级结果,并且您可以使用myComponent函数中的查询调整这些结果 - 如果没有结果,只需记住返回空白查询。
答案 2 :(得分:1)
如果你的genreID和platformID参数添加了默认值“”,那么我认为你可以将你的顶级代码重构为:
<cfif StructKeyExists(url, "titleName") and Len(Trim(url.titleName)) lte 2>
<cfset variables.searchResponse = "invalidString">
<cfelseif StructKeyExists(url, "titleName")>
<cfinvoke component="gz.cfcomp.search" method="searchTitles" returnvariable="searchResult" argumentcollection="#url#">
<cfset variables.searchResponse = "hasResult">
</cfif>
<cfif searchResponse eq "hasResult" and searchResult.recordCount eq 0>
<cfset variables.searchResponse = "noResult">
</cfif>
注意:我建议您将表单方法切换为“获取”以进行此类搜索,以改善用户浏览网站的体验。我已经在代码中将所有表单引用切换为url。
答案 3 :(得分:1)
我的同事告诉我,我们应该简化CFIF声明:
从'CFIF something EQ'“'我们转移到'CFIF Not Len(某事物)',我们更多地使用布尔值为NoResult和HasResult使用布尔值。
无论如何,其他答案都是一些很好的灵感,我需要查看我自己的搜索页面;)