Quickly detecting if a Verity collection exists in CFMX

Posted by Dan on Jan 12, 2006 @ 4:04 PM

I ran into some problems with some code recently that had been written for pre-ColdFusion MX 7. The code in question was designed to create a Verity collection if it didn't already exist.

In past versions of ColdFusion, if you invoked the <cfcollection action="create" /> tag on a collection that already existed, you simply use a cftry/cfcatch to skip doing an error. So, the developer before me had been writing lines of code like this:

<cftry>
    <cfcollection action="create" collection="MyCatalog" path="#someDirectory#" />
    <cfcatch type="any"></cfcatch>
</cftry>

The problem with this is that CFMX 7 no longer throws an error if the collection doesn't exist. It actually tries to re-create the Verity map. The real issue is this takes forever if you have a lot of collections on your server. In my case this was taking 20 seconds to run—which is just not acceptible.

This got me looking into other solutions. I did a search on CFLIB.org and came across a UDF called "collectionExists". This UDF used the <cfcollection action="list" /> to query a list of all Verity collections to see if a collection exists. However, I was having the same problem with this tag as I was with my cftry/cfcatch code. This action takes forever to run when you have a lot of collections on the server. This got me looking for another solution.

What I finally decided would work was to try use <cfsearch> to search over a collection to see if it exists. If the collection doesn't exist, then an error is thrown which I can capture using cftry/cfcatch. What I ended up with is a UDF that looks like this:

<!---
This returns a yes/no value that checks for the existence of a named Verity collection.
Version 3 by Dan G. Switzer, II

@param collection      Collection name to check for. (Required)
@return Returns a boolean.
@author Dan G. Switzer, II (dswitzer@pengoworks.com)
@version 3, Januaray 12, 2006
--->

<cffunction name="collectionExists" returnType="boolean" output="false" hint="This returns a yes/no value that checks for the existence of a named collection.">
    <cfargument name="collection" type="string" required="yes">

    <!---// by default return true //--->
    <cfset var bExists = true />

    <!---// if you can't search the collection, then assume it doesn't exist //--->
    <cftry>
        <cfsearch
            name="SearchItems"
            collection="#arguments.collection#"
            type="explicit"
            criteria="*"
            maxrows="1"
            />

        <cfcatch type="any">
            <!---// if the message contains the string "does not exist", then the collection can't be found //--->
            <cfif cfcatch.message contains "does not exist">
                <cfset bExists = false />
            </cfif>
        </cfcatch>
    </cftry>

    <!---// returns true if search was successful and false if an error occurred //--->
    <cfreturn bExists />

</cffunction>
NOTE:
2006-03-01: I revised this UDF slightly to increase speed.

I've actually posted this UDF to CFLIB, so we'll see if they update the existing function or not. In my testing this method returned ran in a few milliseconds compared to the 20 seconds it was taking before.

Categories: HTML/ColdFusion

9 Comments

  • Did you try playing around with the ServiceFactory.VerityService?
  • I looked in there, but didn't see anything that would return just the collection list. Heck, running the ServiceFactory.VerityService.getCollectioninfo("bookclub") actually takes 23 seconds to run on my box. I really don't understand why this is so slow.
  • Don't know why you system is taking so long to get collection information. 

    You could just check for the collection directory, but that doesn't check the integrity of the collection just that the folder for the collection has been created.

    TYPE="JAVA"
    CLASS="coldfusion.server.ServiceFactory"
    NAME="factory">


  • The delay seems to correlate to the number of collections on the server. I didn't notice the problem until I recently built like 60 different collections. It's been since then that I've noticed this delays.

    The problem with using the factory.VerityService.getCollectiondir() to try and determine if the collection exists is that most of my collections exists outside of the default directory.
  • Very helpful code, reduced page load from 5 seconds to 200ms, thanks.
  • I am seeing the following Exception anytime I call this:

    Invalid search CRITERIA specified: *

    The collections exist, so I am concerned your workaround will not work for us. We are on MX 7.0.2. Any thoughts?
  • @Rob:

    My guess is your collection is corrupt. I'd try deleting the entire collection and re-creating it.
  • This function seems to work for me for checking if a verity collection exists on the server or not

    <cffunction name="veritycollectionexists" returntype="boolean">
        <cfargument name="collectionname" type="string">
      
      <cfset ret=FALSE>
      <cfcollection action="list" name="cfCollections" >
      <cfquery name="checkforit" dbtype="query">select * from cfCollections where cfCollections.name = '#ARGUMENTS.collectionname#'</cfquery>
      <cfif checkforit.recordcount GT 0>
            <cfset ret=TRUE>
      </cfif>
      
      <cfreturn ret>
    </cffunction>
  • @Paul:

    As you can see from my post, the problem with using the cfcollection "list" feature is that (at least under CF7) ran excruciatingly slow if you have a relatively large number of collections (which we do.) If memory serves me correctly, the cfcollection tag was taking 30-60 to run, which was unacceptable.

Add Comment

Leave this field empty