Skip to content

Commit 7fec5d3

Browse files
committed
first commit
0 parents  commit 7fec5d3

File tree

289 files changed

+28269
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

289 files changed

+28269
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/solr-server/solr/data/index/
2+
/solr-server/solr/data/spellcheck/

Application.cfc

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<cfset THIS.name = "cfsolrlibDemo" />
2+
3+
<cffunction name="onApplicationStart">
4+
<cfscript>
5+
// load libraries needed for solrj
6+
var paths = arrayNew(1);
7+
arrayAppend(paths,expandPath("solrj-lib/commons-io-1.4.jar"));
8+
arrayAppend(paths,expandPath("solrj-lib/commons-codec-1.4.jar"));
9+
arrayAppend(paths,expandPath("solrj-lib/slf4j-api-1.5.5.jar"));
10+
arrayAppend(paths,expandPath("solrj-lib/slf4j-jdk14-1.5.5.jar"));
11+
arrayAppend(paths,expandPath("solrj-lib/commons-httpclient-3.1.jar"));
12+
arrayAppend(paths,expandPath("solrj-lib/apache-solr-solrj-3.2.0.jar"));
13+
arrayAppend(paths,expandPath("solrj-lib/geronimo-stax-api_1.0_spec-1.0.1.jar"));
14+
arrayAppend(paths,expandPath("solrj-lib/wstx-asl-3.2.7.jar"));
15+
arrayAppend(paths,expandPath("solrj-lib/jcl-over-slf4j-1.5.5.jar"));
16+
17+
// create an application instance of JavaLoader
18+
APPLICATION.javaloader = createObject("component", "javaloader.JavaLoader").init(paths);
19+
20+
</cfscript>
21+
</cffunction>

NRRcreditsbyartist.pdf

190 KB
Binary file not shown.

components/cfsolrlib.cfc

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<cfscript>
2+
// solr defaults
3+
THIS.host = "localhost";
4+
THIS.port = 8983;
5+
THIS.path = "/solr";
6+
THIS.solrURL = "http://#THIS.host#:#THIS.port##THIS.path#";
7+
THIS.queueSize = 100;
8+
THIS.threadCount = 5;
9+
10+
// java defaults
11+
THIS.javaLoaderInstance = "";
12+
</cfscript>
13+
14+
15+
<cffunction name="init" access="public" output="false" returntype="CFSolrLib">
16+
<cfargument name="javaloaderInstance" required="true" hint="An instance of JavaLoader." />
17+
<cfargument name="host" required="true" type="string" default="localhost" hint="Solr Server host" />
18+
<cfargument name="port" required="false" type="numeric" default="8983" hint="Port Solr server is running on" />
19+
<cfargument name="path" required="false" type="string" default="/solr" hint="Path to solr instance">
20+
<cfargument name="queueSize" required="false" type="numeric" default="100" hint="The buffer size before the documents are sent to the server">
21+
<cfargument name="threadCount" required="false" type="numeric" default="5" hint="The number of background threads used to empty the queue">
22+
<cfargument name="binaryEnabled" required="false" type="boolean" default="true" hint="Should we use the faster binary data transfer format?">
23+
24+
<cfset THIS.javaLoaderInstance = ARGUMENTS.javaloaderInstance />
25+
<cfset THIS.host = ARGUMENTS.host />
26+
<cfset THIS.port = ARGUMENTS.port />
27+
<cfset THIS.path = ARGUMENTS.path />
28+
<cfset THIS.solrURL = "http://#THIS.host#:#THIS.port##THIS.path#" />
29+
<cfset THIS.queueSize = ARGUMENTS.queueSize />
30+
<cfset THIS.threadCount = ARGUMENTS.threadCount />
31+
32+
<cfscript>
33+
// create an update server instance
34+
THIS.solrUpdateServer = THIS.javaLoaderInstance.create("org.apache.solr.client.solrj.impl.StreamingUpdateSolrServer").init(THIS.solrURL,THIS.queueSize,THIS.threadCount);
35+
36+
// create a query server instance
37+
THIS.solrQueryServer = THIS.javaLoaderInstance.create("org.apache.solr.client.solrj.impl.CommonsHttpSolrServer").init(THIS.solrURL);
38+
39+
// enable binary
40+
if (ARGUMENTS.binaryEnabled) {
41+
BinaryRequestWriter = THIS.javaLoaderInstance.create("org.apache.solr.client.solrj.impl.BinaryRequestWriter");
42+
THIS.solrUpdateServer.setRequestWriter(BinaryRequestWriter.init()); // comment this out if you didn't enable binary
43+
THIS.solrQueryServer.setRequestWriter(BinaryRequestWriter.init()); // comment this out if you didn't enable binary
44+
}
45+
</cfscript>
46+
47+
<cfreturn this/>
48+
</cffunction>
49+
50+
<cffunction name="search" access="public" output="false" hint="Search for documents in the Solr index">
51+
<cfargument name="q" type="string" required="true" hint="Your query string" />
52+
<cfargument name="start" type="numeric" required="false" default="0" hint="Offset for results, starting with 0" />
53+
<cfargument name="rows" type="numeric" required="false" default="20" hint="Number of rows you want returned" />
54+
<cfargument name="params" type="array" required="false" default="#arrayNew(1)#" hint="An array of name value pairs of additional params. Values do not need to be only strings." />
55+
56+
<cfset thisQuery = THIS.javaLoaderInstance.create("org.apache.solr.client.solrj.SolrQuery").init(ARGUMENTS.q).setStart(ARGUMENTS.start).setRows(ARGUMENTS.rows) />
57+
<cfloop array="#ARGUMENTS.params#" index="thisParam">
58+
<cfset thisQuery.setParam(thisParam.name,thisParam.value)>
59+
</cfloop>
60+
61+
<!--- we do this instead of making the user call java functions, to work around a CF bug --->
62+
<cfset response = THIS.solrQueryServer.query(thisQuery) />
63+
<cfset ret = structNew() />
64+
<cfset ret.results = response.getResults() / >
65+
<cfset ret.spellCheck = response.getSpellCheckResponse() / >
66+
67+
<cfreturn duplicate(ret) /> <!--- duplicate clears out the case-sensitive structure --->
68+
</cffunction>
69+
70+
<cffunction name="add" access="public" output="false" hint="Add a document to the Solr index">
71+
<cfargument name="doc" type="array" required="true" hint="An array of field objects, with name, value, and an optional boost attribute. {name:""Some Name"",value:""Some Value""[,boost:5]}" />
72+
<cfargument name="docBoost" type="numeric" required="false" hint="Value of boost for this document." />
73+
74+
<cfset thisDoc = THIS.javaLoaderInstance.create("org.apache.solr.common.SolrInputDocument").init() />
75+
<cfif isDefined("ARGUMENTS.docBoost")>
76+
<cfset thisDoc.setDocumentBoost(ARGUMENTS.docBoost) />
77+
</cfif>
78+
79+
<cfloop array="#ARGUMENTS.doc#" index="thisParam">
80+
<cfif isDefined("thisParam.boost")>
81+
<cfset thisDoc.addField(thisParam.name,thisParam.value,thisParam.boost) />
82+
<cfelse>
83+
<cfset thisDoc.addField(thisParam.name,thisParam.value) />
84+
</cfif>
85+
</cfloop>
86+
87+
<cfreturn THIS.solrUpdateServer.add(thisDoc) />
88+
</cffunction>
89+
90+
<cffunction name="addField" access="public" output="false" returnType="array" hint="Creates a field object and appends it to the array. This is a helper method for adding to your index.">
91+
<cfargument name="documentArray" required="true" type="array" hint="An array to add your document field to." />
92+
<cfargument name="name" required="true" type="string" hint="Name of your field." />
93+
<cfargument name="value" required="true" hint="Value of your field." />
94+
<cfargument name="boost" required="false" type="numeric" hint="An array to add your document field to." />
95+
96+
<cfset thisField = structNew() />
97+
<cfset thisField.name = ARGUMENTS.name />
98+
<cfset thisField.value = ARGUMENTS.value />
99+
<cfif isDefined("ARGUMENTS.boost")>
100+
<cfset thisField.boost = ARGUMENTS.boost />
101+
</cfif>
102+
103+
<cfset arrayAppend(ARGUMENTS.documentArray,thisField) />
104+
105+
<cfreturn ARGUMENTS.documentArray />
106+
</cffunction>
107+
108+
<cffunction name="addFile" access="public" output="false" hint="Creates a field object for appending to an array. This is a helper method for adding to your index.">
109+
<cfargument name="id" required="true" hint="The unique ID of the document" />
110+
<cfargument name="file" required="true" type="string" hint="path to the document to be added" />
111+
<cfargument name="fmap" required="false" type="struct" hint="The mappings of document metadata fields to index fields." />
112+
<cfargument name="saveMetadata" required="false" type="boolean" default="true" hint="Store non-mapped metadata in dynamic fields" />
113+
<cfargument name="metadataPrefix" required="false" type="string" default="attr_" hint="Metadata dynamic field prefix" />
114+
115+
<cfset docRequest = THIS.javaLoaderInstance.create("org.apache.solr.client.solrj.request.ContentStreamUpdateRequest").init("/update/extract") />
116+
<cfset docRequest.addFile(createObject("java","java.io.File").init(ARGUMENTS.file)) />
117+
<cfset docRequest.setParam("literal.id",ARGUMENTS.id) />
118+
<cfif ARGUMENTS.saveMetadata>
119+
<cfset docRequest.setParam("uprefix",metadataPrefix) />
120+
</cfif>
121+
<cfif isDefined("ARGUMENTS.fmap")>
122+
<cfloop list="#structKeyList(ARGUMENTS.fmap)#" index="thisKey">
123+
<cfset docRequest.setParam("fmap.#thisKey#",ARGUMENTS.fmap[thisKey]) />
124+
</cfloop>
125+
</cfif>
126+
127+
<cfreturn THIS.solrUpdateServer.request(docRequest) />
128+
</cffunction>
129+
130+
<cffunction name="deleteByID" access="public" output="false" hint="Delete a document from the index by ID">
131+
<cfargument name="id" type="string" required="true" hint="ID of object to delete.">
132+
133+
<cfset THIS.solrUpdateServer.deleteByID(ARGUMENTS.id) />
134+
</cffunction>
135+
136+
<cffunction name="deleteByQuery" access="public" output="false" hint="Delete a document from the index by Query">
137+
<cfargument name="q" type="string" required="true" hint="Query string to delete objects with.">
138+
139+
<cfset THIS.solrUpdateServer.deleteByQuery(ARGUMENTS.q) />
140+
</cffunction>
141+
142+
<cffunction name="resetIndex" access="public" output="false" hint="Clear out the index.">
143+
<cfset THIS.deleteByQuery("*:*") />
144+
<cfset THIS.commit() />
145+
<cfset THIS.optimize() />
146+
</cffunction>
147+
148+
<cffunction name="rollback" access="public" output="false" hint="Roll back all pending changes to the index">
149+
<cfset THIS.solrUpdateServer.rollback() />
150+
</cffunction>
151+
152+
<cffunction name="commit" access="public" output="false" hint="Commit all pending changes to the index">
153+
<cfset THIS.solrUpdateServer.commit() />
154+
</cffunction>
155+
156+
<cffunction name="optimize" access="public" output="false" hint="Commit all pending changes to the index">
157+
<cfset THIS.solrUpdateServer.optimize() />
158+
</cffunction>

index.cfm

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<cfset sampleSolrInstance = createObject("component","components.cfsolrlib").init(APPLICATION.javaloader,"localhost","8983","/solr") />
2+
<html>
3+
<head>
4+
<title>CFSolrLib 2.0</title>
5+
</head>
6+
<body>
7+
<h2>Welcome to CFSolrLib</h2>
8+
<p>CFSolrLib is a library that lets you interact directly with a Solr server, using the native java client library.</p>
9+
10+
<h2>Requirements</h2>
11+
<p>
12+
You need a few basic things to use CFSolrLib 2:<br/>
13+
<ul>
14+
<li>A Solr server, version 3.1 or greater. This was built &amp; tested with Solr 3.2. This library will not work with earlier versions of Solr.</li>
15+
<li><a href="http://wiki.apache.org/solr/Solrj">SolrJ</a> - The Solr java client library and supporting java libraries.</li>
16+
<li>Mark Mandel's <a href="http://www.compoundtheory.com/?action=javaloader.index">JavaLoader</a>, to load SolrJ.</li>
17+
</ul>
18+
</p>
19+
20+
<h2>Installation</h2>
21+
<p>I've included everything you need right here... which also means that there might be updates to the included software. Let's quickly go over what all is included, and what I have pre-configured for you.</p>
22+
<ul>
23+
<li>components/</li>
24+
<ul>
25+
<li>This directory houses the CFSolrLib cfc. In your actual app, this cfc doesn't need to be accessable from the web.</li>
26+
</ul>
27+
<li>index.cfm</li>
28+
<ul>
29+
<li>You're looking at it right now.</li>
30+
</ul>
31+
<li>javaloader/</li>
32+
<ul>
33+
<li>The standard JavaLoader install. Again, this doesn't need to be in your root directory, and if you already use JavaLoader, you don't need another copy.</li>
34+
</ul>
35+
<li>solr-server/</li>
36+
<ul>
37+
<li>A copy of Solr 3.2 "example" directory.</li>
38+
<li>solr-server/solr/conf/schema.xml</li>
39+
<ul>
40+
<li>This schema file has been simplified for the examples.</li>
41+
</ul>
42+
<li>solr-server/work/Jetty_[...]/webapp/WEB-INF/lib</li>
43+
<ul>
44+
<li>This directory is normally created by the Jetty J2EE server using solr.war file. I've added in the neccessary Java files to support reading rich documents (Apache Tika/Solr Cell). These libraries can be found in the contrib/dataimporthandler directory in a standard Solr download, and need to be placed in the lib directory of your deployment.</li>
45+
</ul>
46+
</ul>
47+
<li>solrj-lib/</li>
48+
<ul>
49+
<li>A collection of the java files needed to run the SolrJ client library. These files are normally located in various places in the solr-server directory, but copied here for conviencnce.</li>
50+
</ul>
51+
</ul>
52+
<p>In order to start the Solr server, you will need to run a command from the command line, inside the solr-server directory. Make sure you don't have another Solr server running, including the one built-in to CF9. If you are on Linux/OS X, you might need to run the command with sudo.</p>
53+
<ul>
54+
<li><strong>java -jar start.jar</strong></li>
55+
</ul>
56+
57+
<h2>Examples</h2>
58+
<p>There are to basic examples, one for indexing content, and one for searching content. This is not a Solr tutorial, this just shows how to get your data in &amp; out using this CF library.</p>
59+
60+
<ul>
61+
<li><a href="indexExample.cfm">Indexing Example</a> (requires the CFArtGallery datasource)</li>
62+
<li><a href="searchExample.cfm">Search Example</a></li>
63+
</ul>
64+
65+
<p>The point of the examples is the CF code, not the HTML that you'll see in the browser, so be sure to dig in!</p>
66+
67+
<h2>Ways to share your appriciation</h2>
68+
<p>If you like this, or any of my other open-source projects, you're always welcome to take a peek at my <a href="http://www.amazon.com/wishlist/172M0XGIRQ2S8">Amazon Wish List</a>.</p>
69+
</body>
70+
</html>

indexExample.cfm

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<cfset sampleSolrInstance = createObject("component","components.cfsolrlib").init(APPLICATION.javaloader,"localhost","8983","/solr") />
2+
3+
<cfquery name="getArt" datasource="cfartgallery">
4+
SELECT artID, artname, description
5+
FROM art
6+
</cfquery>
7+
8+
<cfscript>
9+
// example for indexing content from a database
10+
for (i=1;i LTE getArt.recordcount;i=i+1) {
11+
thisDoc = arrayNew(1);
12+
13+
sampleSolrInstance.addField(thisDoc,"id",getArt.artID[i]);
14+
sampleSolrInstance.addField(thisDoc,"title",getArt.artname[i]);
15+
sampleSolrInstance.addField(thisDoc,"text",getArt.description[i]);
16+
sampleSolrInstance.add(thisDoc);
17+
}
18+
19+
// example for indexing content from a rich file
20+
myFile = expandPath("NRRcreditsbyartist.pdf");
21+
fmap = structNew();
22+
fmap.title = "title";
23+
fmap.content = "content";
24+
sampleSolrInstance.addFile("file-1",myFile,fmap);
25+
26+
sampleSolrInstance.commit(); // do a final commit of our changes
27+
sampleSolrInstance.optimize(); // since we're all done, optimize the index
28+
</cfscript>
29+
30+
<html>
31+
<head>
32+
<title>CFSolrLib 2.0 | Indexing example</title>
33+
</head>
34+
<body>
35+
<h2>Indexing</h2>
36+
37+
<p>Done. There's nothing to output, you'll want to look at the CF source.</p>
38+
</body>
39+
</html>

0 commit comments

Comments
 (0)