We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 37286
    • 160 Posts
    I've been working on a large project and I'm trying to figure out if there is any performance benefit to using the getObjectGraph to make updates to the database. For example, I have about five tables tied together. So my object graph might look something like:
    getObjectGraph('Main','{ "tbl1":{ "sub1":{}, "sub2":{} }, "tbl2":{}, "tbl3":{} }', $main_id)

    However, when I do an update I may only update a single field in tbl2 or sub1. If I do multiple getObject calls, sometimes I just need to check if something exists, and not have to update the table at all. For example, is it faster to do an "IN" or "NOT IN" query on a table than to grab a object graph and then iterate through the collection?

    Also, are there any known problems with saving large graphs? Any input would be appreciated.
      • 34084 ☆ A M B ☆
      • 756 Posts
      It all really depends on your data model and what the frequency and quantity of related data get altered in the update process. I generally only use the getObjectGraph when I know as a business rule that I need to touch related objects, for me mostly on adding and editing existing. The other thing to keep in mind is the getObjectGraph will use more memory, so if you don't need to grab all the related objects save the processing time and resources and just request them when you need to. The short is it all depends on your data set(s) size and frequency of actually accessing the related data objects on which will provide a better performance result.

      That is my opinion.

      CHeers
        Evo Revo // Ubuntu, CentOS, Win // Apache 2x, Lighttp (Lighty)
        Visit CharlesMx.com for latest news and status updates.
        • 37286
        • 160 Posts
        This has to do with importing data from a data feed, so I never know what needs to be updated in which tables until the feed is sent. That's kind of the problem. They send the entire xml file every time and I have to parse the thing and see what changed. I almost need a "where" clause on every field.
          • 34084 ☆ A M B ☆
          • 756 Posts
          Quote from: insomnix at Apr 03, 2013, 02:44 PM
          This has to do with importing data from a data feed, so I never know what needs to be updated in which tables until the feed is sent. That's kind of the problem. They send the entire xml file every time and I have to parse the thing and see what changed. I almost need a "where" clause on every field.

          Can you provide a sample of what your doing? Without more information it would be though to provide specific guidance for your situation.

          Cheers
            Evo Revo // Ubuntu, CentOS, Win // Apache 2x, Lighttp (Lighty)
            Visit CharlesMx.com for latest news and status updates.
            • 37286
            • 160 Posts
            Below is shortened example of the xml file I receive
            <item sku="12345" brand="brand" title="title" cost="11.11" msrp="15.55" >
            	<freightdata length="8.00" width="6.50" height="1.25" weight="0.24" ORMD="N" bulk="N" />
            	<description>Part description</description>
            	<features>
            		<feat value="feat 1" />
            		<feat value="feat 2" />
            	<features>
            	<attributes>
            		<attr type="size" value="lg" />
            		<attr type="color" value="white" />
            	</attributes>
            	<location>
            		<loc id="1" quantity="4" estimatedArrival="" />
            		<loc id="2" quantity="0" estimatedArrival="" />
            		<loc id="3" quantity="0" estimatedArrival="" />
            	</location>
            </item>
            


            I have a table to hold the item in the primary table. Then I have another table that maintains the location info like address and phone, there are three locations that we'll just call 1,2, & 3. Then the third table holds the actual qty's for each location. So the item is tied to the location_qtys, which has a reference to the location_info. It looks something like:
            getObjectGraph('item','{ "location_qtys":{ "location_info":{} } }', $main_id)

            Then there are a few more tables that hold attributes and features. With those added, it looks like:
            getObjectGraph('item','{ "location_qtys":{ "location_info":{} }, "features":{},"attributes":{} }', $main_id)

            There are some reference tables as well, but I'm not showing those here, just the actual feed info.
              • 3749
              • 24,544 Posts
              If you have a variable ($c) set for the criteria, you can also do $modx->getCount($c), which might give you a faster test.

              It's difficult to say whether cascaded tests with getCount() would be faster than using getCollectionGraph() without benchmarking since it would depend on the odds of having to make further queries.
                Did I help you? Buy me a beer
                Get my Book: MODX:The Official Guide
                MODX info for everyone: http://bobsguides.com/modx.html
                My MODX Extras
                Bob's Guides is now hosted at A2 MODX Hosting
                • 32699 ☆ A M B ☆
                • 427 Posts
                In my experience $xpdo->getCount() on cascaded result sets isn't overly accurate. I'd stay away from it, except for straight getCollection() type queries.

                Try something like this:

                    /**
                     * Counts the items in a multi-dimensional array and returns the total count
                     *
                     * @param array $a
                     *            A multidimensional array
                     * @return int The number of items in an array or zero if not an array
                     */
                    public function count_nested_array_keys (array $a) {
                        $out = (is_array($a)) ? count($a, COUNT_RECURSIVE) : 0;
                        return $out;
                    }
                


                Simply perform your getCollectionGraph(), getObjectGraph() retrieve a collection and throw it at the function.

                I'm pretty sure it will work for you.

                Not sure if you have seen this tucked into the xPDO class:

                 /**
                     * Update field values across a collection of xPDOObjects.
                     *
                     * @param string $className Name of the class to update fields of.
                     * @param array $set An associative array of field/value pairs representing the updates to make.
                     * @param mixed $criteria An xPDOCriteria object or representation.
                     * @return bool|int The number of instances affected by the update or false on failure.
                     */
                    public function updateCollection($className, array $set, $criteria= null) {...}



                I'm building against a 10 year old WSDL platform now so I feel your pain.

                Fortunately, I can grab each section of the feed through a couple dozen API pulls so I can target the data set I want, do a getCollection, loop through it and update only those records which have changed by comparing each object's field against its incoming counterpart. If a change is detected, then I save the current date set over the top of the old one.

                Here's a post with some info which may help: http://stackoverflow.com/questions/9866920/whats-the-fastest-way-to-compare-two-objects-in-php
                PHP.net: http://php.net/manual/en/language.oop5.object-comparison.php

                The second link suggests you could create two objects with the data (supposedly the same one base on some fixed key on the incoming data set):

                $testObj = $modx->newObject('somwClass', $incomingArray);
                
                $currentObj = $modx->getObject('someClass', $testObj->get('remoteKey');
                

                Then run them through some comparison apparatus.

                Hope this helps.

                  Get your copy of MODX Revolution Building the Web Your Way http://www.sanitypress.com/books/modx-revolution-building-the-web-your-way.html

                  Check out my MODX || xPDO resources here: http://www.shawnwilkerson.com
                  • 37286
                  • 160 Posts
                  I'll definitely take a look at that.

                  I did do some tests using the object collection graph vs multiple query's and found that if I use a combination I get a fairly decent result. For example, updating the primary table with the locations information worked well, but adding features and attributes to that collection graph really slowed down the process. I think branching out into to many directions is what is slowing down this process. Breaking it down into smaller chunks appears to have helped.

                  Thanks for the insights.
                    • 42602
                    • 81 Posts
                    I'll just go along with Shawn,

                    the getCount is 90% of the time accurate when working with really, really, really simple queries. If you subquery, a math function or if/else in the query. You will get unexpected results.

                    The function basically clears you whole SELECT * statement, so if you have anything special there from normal fields. The function does not work,