I don't think that there is a problem with your approach, its basically the same way I've written recursive functions for trees. However recursive functions are notoriously slow, and instantiating reactor gateway and record objects over and over is only going to compound the problem.
The simple option would be to cut reactor out of the loop here, just use straight queries, it will be much faster. Secondly, and this is the way I now handle trees is to drop the recursion all together. Have a look at this sitepoint article http://www.sitepoint.com/article/hierarchical-data-database and some of the referenced material. It describes how to implement Modified Preorder Tree Traversal (and convert your old data). Using this you can return your navigation tree with one query, including the nesting level. The disadvantage is that inserting data into the table is more complex, but for a navigation I'm guessing that it won't change too often. My approach to adding/deleting nodes is the same as they describe in the "Adding a node" section, I keep my parent column and call a rebuildtree() function after the data is altered. It's not the most efficient, but for trees that get vastly more reads, than writes it’s a good option. Also take a look at Barneyb's blog, to download his treemanager cfc http://www.barneyb.com/blog/archives/000532.jsp I've used this in some of my reactor records that return tree data. Cheers, Chris -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Doug Boude Sent: 14 April 2006 14:59 To: [email protected] Subject: [Reactor For CF] Recursive function using reactor Hi all. I'm building an app using model glue and reactor. I'm having an issue with a function I wrote that returns my navigation to me, appropriately nested. The function is a recursive one, and works as designed, no problem there. BUT, it's painfully slow (18 seconds against a table with only 20 records), even with debugging and reactor regeneration disabled. SO, I'm wondering if any of you can look at how I've approached this and tell me if anything jumps out at you as obviously inefficient. Any input is greatly appreciated! Doug :0) The specs: String value returned by the function: <div id="menu0">Administration</div> <div id="menu1">view reports</div> <div id="menu1">search employees</div> <div id="menu2">easy on the bottom line</div> <div id="menu1">enrollment stats</div> <div id="menu1">system reports</div> <div id="menu1">Company profile</div> <div id="menu1">manage system users</div> <div id="menu1">message center</div> <div id="menu0">Enrollment</div> <div id="menu1">new hire enrollment</div> <div id="menu1">life status event</div> <div id="menu1">view current benefits</div> <div id="menu0">About Us</div> <div id="menu0">Cwes features</div> <div id="menu1">streamlined open enrollment</div> <div id="menu1">customizable reports</div> <div id="menu1">ease of use</div> <div id="menu1">one stop shop</div> <div id="menu0">Contact Us</div> My nav table structure: NavigationID (primary key, auto incrementing integer); name (varchar, name of my nav item); output_text (varchar, text to use for the nav item); link (varchar, link for the nav item); parentid (integer, ID of the parent navigation item (= navigationID)); navorder (tinyint, sort order for navigation) The CFC performing the nav building: <cfcomponent displayname="Controller" output="false" hint="" extends="ModelGlue.Core.Controller"> <cfset variables.reactor = application.recordfactory /> <cfset variables.navcontainer = "" /> <cffunction name="Init" access="Public" returnType="controller.navcontroller" output="false" hint= ""> <cfargument name="ModelGlue" required="true" type="ModelGlue.ModelGlue" /> <cfargument name="InstanceName" required="true" type="string" /> <cfset super.Init(arguments.ModelGlue) /> <cfreturn this /> </cffunction> <cffunction name="getNav" access="public" returnType="void" output="false"> <cfargument name="event" type="ModelGlue.Core.Event" required="false"> <cfargument name="parentID" type="numeric" required="yes" default=0 /> <cfargument name="level" type="numeric" required="yes" default=0 /> <cfset var objNav = "" /> <cfset var objItem = "" /> <!--- grab all the elements whose parent is 'arguments.parentID' ---> <cfset objNav = variables.reactor.creategateway("navparent").getByFields(parentid=arguments. parentid) /> <!--- loop through query ---> <cfloop query="objNav"> <!--- add this item to global variable ---> <cfset variables.navcontainer = variables.navcontainer & "<div id=""menu" & arguments.level & """>" & objNav.name & "</div>" & chr(10) /> <!--- check for children. If there are any, call this function recursively ---> <cfif variables.reactor.createrecord("navparent").load(navigationid=objNav.navigationid). getnavchilditerator().hasmore()> <cfset getNav(parentID = objNav.navigationID, level = arguments.level + 1) /> </cfif> </cfloop> <!--- loop finished ---> <!--- return final variable ---> <cfif arguments.level eq 0> <cfset arguments.event.setValue("navtext",variables.navcontainer) /> </cfif> </cffunction> </cfcomponent> The Reactor XML section regarding nav: <object name="Navigation"></object> <object name="Navigation" alias="NavParent"> <hasMany name="navChild"> <relate from="navigationID" to="ParentID"></relate> </hasMany> </object> <object name="Navigation" alias="navChild"> <hasOne name="NavParent"> <relate from="parentID" to="NavigationID"></relate> </hasOne> </object> E涊Ѳ*1xyȽ VryrG

