{"id":172,"date":"2012-03-08T11:55:53","date_gmt":"2012-03-08T16:55:53","guid":{"rendered":"http:\/\/www.thefaberfamily.org\/search-smith\/?p=172"},"modified":"2012-03-08T12:05:57","modified_gmt":"2012-03-08T17:05:57","slug":"coldfusion-and-solr-dealing-with-the-results","status":"publish","type":"post","link":"http:\/\/www.thefaberfamily.org\/search-smith\/2012\/03\/coldfusion-and-solr-dealing-with-the-results\/","title":{"rendered":"ColdFusion and Solr: Dealing with the results"},"content":{"rendered":"<p>The Solr web service allows you to return results in either XML format or JSON (the format is XML by default; to return results in JSON format, add the parameter &#8220;wt=json&#8221; to your Solr query string). Suppose we run a query on the Solr collection <strong>myindex<\/strong>. There are three ways we can search this collection: (1) we could use the <code>&lt;cfsearch&gt;<\/code> tag; (2) we could use the Solr web service and return XML; or (3) we could use the Solr web service and return JSON. We&#8217;ve <a title=\"Solr Query Parameters\" href=\"http:\/\/www.thefaberfamily.org\/search-smith\/2012\/01\/solr-query-parameters\/\">talked about <code>&lt;cfsearch&gt;<\/code> and its limitations before<\/a> so I&#8217;ll limit this discussion to the second and third options.<\/p>\n<p><strong>XML:<\/strong><\/p>\n<pre>&lt;cfhttp url=\"http:\/\/localhost:8983\/solr\/myindex?q=*:*&amp;fl=*,score\" result=\"myresult\" \/&gt;<\/pre>\n<p><strong>JSON:<\/strong><\/p>\n<pre>&lt;cfhttp url=\"http:\/\/localhost:8983\/solr\/myindex?q=*:*&amp;fl=*,score&amp;wt=json\" result=\"myresult\" \/&gt;<\/pre>\n<p>In each case (XML or JSON), ColdFusion has powerful functions that help you manage the data without needing to parse it manually. Typically I create a friendly query that I can return to the front-end developer that he can use in place of a SQL query or <code>&lt;cfsearch&gt;<\/code> result.<\/p>\n<pre>&lt;cfset search_results = queryNew(\"id,title,description,pubdate,journal_name,author_name,num_reads,score\"\r\n                              \u00a0, \"CF_SQL_INTEGER,CF_SQL_VARCHAR,CF_SQL_CLOB,CF_SQL_DATE,CF_SQL_VARCHAR,CF_SQL_VARCHAR,CF_SQL_INTEGER,CF_SQL_DOUBLE\")\r\n\/&gt;\r\n&lt;!--- We're using our <a title=\"ColdFusion 9: Indexing custom fields in Solr\" href=\"http:\/\/www.thefaberfamily.org\/search-smith\/2011\/12\/coldfusion-9-indexing-custom-fields-in-solr\/\">articles index mentioned in a previous post<\/a> ---&gt;<\/pre>\n<p><strong>XML:<\/strong><\/p>\n<pre>&lt;cfif isXML(myresult)&gt;\r\n    &lt;cfset xml_result = XMLParse(myresult.fileContent) \/&gt;\r\n    &lt;!--- continue processing ---&gt;\r\n&lt;\/cfif&gt;<\/pre>\n<p><strong>JSON:<\/strong><\/p>\n<pre>&lt;cfif isJSON(myresult)&gt;\r\n    &lt;cfset json_result = deserializeJSON(myresult.fileContent) \/&gt;\r\n    &lt;!--- continue processing ---&gt;\r\n&lt;\/cfif&gt;<\/pre>\n<p>In either case we will iterate over our results structure and put the results in our friendly query.<\/p>\n<p><strong>JSON:<\/strong><br \/>\nThe JSON structure is particularly friendly for our purposes. First, let&#8217;s get the number of results and the maximum score:<\/p>\n<pre>&lt;cfset result_cnt = json_result.response.numFound \/&gt;\r\n&lt;cfset max_score = json_result.response.maxScore \/&gt;<\/pre>\n<p>These fields aren&#8217;t absolutely necessary, of course. In particular, maxScore seems superfluous but it might be useful if you&#8217;re converting from Verity to Solr and need scores in a % format. The Verity search engine scores results between 0 and 1, which is easily converted to a percentage; while Solr has no maximum score. So to get a Verity-style score, simply divide each result&#8217;s score by maxScore.<\/p>\n<p>Now we simply loop over the <code>docs <\/code>array of the response:<\/p>\n<pre>&lt;cfloop array=\"#json_result.response.docs#\" index=\"doc\"&gt;\r\n    &lt;cfif structKeyExists(doc, \"id\") AND structKeyExists(doc, \"title\")&gt;\r\n        &lt;!--- Both id and title are absolutely required ---&gt;\r\n        &lt;cfset queryAddRow(search_results) \/&gt;\r\n        &lt;cfset querySetCell(search_results, \"id\", doc[id]) \/&gt;\r\n        &lt;cfset querySetCell(search_results, \"title\", doc[title]) \/&gt;\r\n        &lt;cfset querySetCell(search_results, \"score\", doc[score] \/ max_score) \/&gt;\r\n       \u00a0&lt;cfif structKeyExists(doc, \"description\")&gt;\r\n            &lt;cfset querySetCell(search_results, \"description\", doc[description]) \/&gt;\r\n        &lt;\/cfif&gt;\r\n        &lt;cfif structKeyExists(doc, \"pub_date\")&gt;\r\n            &lt;cfset querySetCell(search_results, \"pub_date\", doc[pub_date]) \/&gt;\r\n        &lt;\/cfif&gt;\r\n        &lt;cfif structKeyExists(doc, \"journal_name\")&gt;\r\n            &lt;cfset querySetCell(search_results, \"journal_name\", doc[journal_name]) \/&gt;\r\n        &lt;\/cfif&gt;\r\n        &lt;cfif structKeyExists(doc, \"author_name\")&gt;\r\n            &lt;cfset querySetCell(search_results, \"author_name\", doc[author_name]) \/&gt;\r\n        &lt;\/cfif&gt;\r\n        &lt;cfif structKeyExists(doc, \"read_cnt\")&gt;\r\n            &lt;cfset querySetCell(search_results, \"read_cnt\", doc[read_cnt]) \/&gt;\r\n        &lt;\/cfif&gt;\r\n    &lt;\/cfif&gt;\r\n&lt;\/cfloop&gt;<\/pre>\n<p>Dealing with XML results is a bit more complicated so I will discuss that in a subsequent post or in an update to this one. Suffice it to say that the approach will be very similar &#8211; we will iterate over the results and store them in a friendly query.<\/p>\n<div class=\"simple_likebuttons_container_small\">\r\n      <div class=\"simple_likebuttons_googleplus\">\r\n        <g:plusone size=\"medium\" count=\"false\" href=\"http:\/\/www.thefaberfamily.org\/search-smith\/2012\/03\/coldfusion-and-solr-dealing-with-the-results\/\"><\/g:plusone>\r\n      <\/div>\r\n    \r\n      <div class=\"simple_likebuttons_twitter simple_likebuttons_twitter_s\">\r\n        <a href=\"https:\/\/twitter.com\/share\" class=\"twitter-share-button\" data-count=\"none\" data-url=\"http:\/\/www.thefaberfamily.org\/search-smith\/2012\/03\/coldfusion-and-solr-dealing-with-the-results\/\" data-lang=\"en\">Tweet<\/a>\r\n      <\/div>\r\n    \r\n      <div class=\"simple_likebuttons_facebook\">\r\n        <div id=\"fb-root\"><\/div>\r\n        <script>(function(d, s, id) {\r\n          var js, fjs = d.getElementsByTagName(s)[0];\r\n          if (d.getElementById(id)) {return;}\r\n          js = d.createElement(s); js.id = id;\r\n          js.src = \"\/\/connect.facebook.net\/en_US\/all.js#xfbml=1\";\r\n          fjs.parentNode.insertBefore(js, fjs);\r\n        }(document, \"script\", \"facebook-jssdk\"));<\/script>\r\n        <div class=\"fb-like\" data-href=\"http:\/\/www.thefaberfamily.org\/search-smith\/2012\/03\/coldfusion-and-solr-dealing-with-the-results\/\" data-send=\"false\" data-layout=\"button_count\" data-show-faces=\"false\" data-width=\"90\"><\/div>\r\n      <\/div>\r\n    <\/div>","protected":false},"excerpt":{"rendered":"<p>The Solr web service allows you to return results in either XML format or JSON (the format is XML by default; to return results in JSON format, add the parameter &#8220;wt=json&#8221; to your Solr query string). Suppose we run a query on the Solr collection myindex. There are three ways we can search this collection: [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,3],"tags":[87,48,13,68,67,69,88,66],"class_list":["post-172","post","type-post","status-publish","format-standard","hentry","category-coldfusion","category-solr","tag-coldfusion","tag-json","tag-query","tag-queryaddrow","tag-querynew","tag-querysetcell","tag-solr","tag-xml"],"_links":{"self":[{"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/posts\/172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/comments?post=172"}],"version-history":[{"count":10,"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/posts\/172\/revisions"}],"predecessor-version":[{"id":202,"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/posts\/172\/revisions\/202"}],"wp:attachment":[{"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/media?parent=172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/categories?post=172"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.thefaberfamily.org\/search-smith\/wp-json\/wp\/v2\/tags?post=172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}