docs: function( params, cb ){
  
      var self = this;
      var layer = this;
      var selector;
      var updateObject, unsetObject, relativeUnsetObject, relativeUpdateObject;
      var id, k, prefix, filters, mongoParameters;
  
      // Paranoid checks and sane defaults for params
      if( typeof( params ) !== 'object' || params === null ) params = {};
  
      var rnd = Math.floor(Math.random()*100 );
      consolelog( "\n");
      consolelog( rnd, "ENTRY: _updateParentsRecords on table", self.table );
      consolelog( rnd, 'Params:' );
      consolelog( require('util').inspect( params, { depth: 10 } ) );
  
      consolelog( rnd, "Cycling through: ", self.parentTablesArray );
  
      // Cycle through each parent of the current layer
      async.eachSeries(
        self.parentTablesArray,
        function( parentTableData, cb ){
  
          consolelog( rnd, "Working on ", parentTableData.layer.table );
  
          var parentLayer = parentTableData.layer;
          var nestedParams = parentTableData.nestedParams;
  
          // Figure out the field name, relative to _children.XXXXX
          // - For multiple, it will just be the table's name
          // - For lookups, it will be the localField value in nestedParams
          var field;
          switch( nestedParams.type ){
            case 'multiple': field = self.table; break;
            case 'lookup'  : field = nestedParams.localField; break;
            default        : return cb( new Error("type needs to be 'lookup' or 'multiple'") );
          }
          consolelog( "FIELD:", field );
          consolelog( "PARAMETERS:", nestedParams );
          consolelog( "PARAMETERS TYPE:", nestedParams.type );
  
          consolelog( rnd, "fielddd for ", nestedParams.type, "is:", field );
  
          /* THREE CASES:
            * CASE #1: Insert
            * CASE #2: Update
            * CASE #3: Delete
  
                                *** DO NOT OPTIMISE THIS CODE ***
  
            I REPEAT: DO NOT OPTIMISE THIS CODE.
            This code has the potential to become the most uncomprehensible thing ever written. Worse than Perl.
            Optimising here is simple -- and even tempting. DON'T. Clarity here is MUCH more important than
            terseness.
          */
  
          // CASE #1 -- INSERT
  
          if( params.op === 'insert' ){
  
            if( nestedParams.type === 'multiple' ){
  
              consolelog( rnd, "CASE #1 (insert, multiple)" );
  
              // Assign the parameters
              var record = params.record;
  
              // JOIN QUERY (reversed, look for parent)
              var mongoSelector = {};
              Object.keys( nestedParams.join ).forEach( function( joinKey ){
                mongoSelector[ nestedParams.join[ joinKey ] ] = record[ joinKey ];
              });
              mongoSelector._clean = true;
  
              // The updateRecord variable is the same as record, but with uc fields and _children added
              var insertRecord = {};
              for( k in record ){
                if( ! record.hasOwnProperty( k ) ) continue;
                insertRecord[ k ] = record[ k ];
              }
              self._addUcFields( insertRecord );
              insertRecord._children = {};
  
              updateObject = { '$push': {} };
              updateObject.$push[ '_children' + '.' + field ] = { '$each': [ insertRecord ], '$slice': -1000 };
  
              consolelog( rnd, "The mongoSelector is:", mongoSelector  );
              consolelog( rnd, "The update object is: ");
              consolelog( require('util').inspect( updateObject, { depth: 10 } ) );
  
              parentLayer.collection.update( mongoSelector, updateObject, function( err, total ){
                if( err ) return cb( err );
                // This check s commented out as there might (or there WILL) be parent tables without
                // the matching id
                //if( total === 0 ) return cb( new Error("Record not found while adding entry to child table") );
                consolelog( rnd, "Record inserted in sub-array: ", total );
  
                cb( null );
  
              });
  
            // noop
            } else if( nestedParams.type === 'lookup' ){
  
              return cb( null );
            }
  
          // CASE #2 -- UPDATE
  
          } else if( params.op === 'updateOne' || params.op === 'updateMany' ){
  
            if( params.op === 'updateOne' ){
  
              consolelog( rnd, "CASE #2 (updateOne)", params.op );
  
              // Assign the parameters
              id = params.id;
              updateObject = params.updateObject;
              unsetObject = params.unsetObject;
  
              prefix = '_children.' + field + ( nestedParams.type === 'multiple' ?  '.$.' : '.' ) ;
  
              // Make up relative update objects based on the original ones,
              // with extra path added
              relativeUpdateObject = {};
              for( k in updateObject ){
                if( !updateObject.hasOwnProperty( k ) ) continue;
                relativeUpdateObject[ prefix + k ] = updateObject[ k ];
              }
              relativeUnsetObject = {};
              for( k in unsetObject ){
                if( !unsetObject.hasOwnProperty( k ) ) continue;
                relativeUnsetObject[ prefix + k ] = unsetObject[ k ];
              }
  
              selector = {};
              selector[ '_children.' + field + "." + self.idProperty ] = id;
              selector._clean = true;
              consolelog( rnd, "SELECTOR:" );
              consolelog( rnd, selector );
  
              var u = { $set: relativeUpdateObject };
              if( Object.keys( relativeUnsetObject ).length ) u.$unset = relativeUnsetObject;        
              parentLayer.collection.update( selector, u, { multi: true }, function( err, total ){
                if( err ) return cb( err );
  
                consolelog( rnd, "Updated:", total, "records" );
                
                return cb( null );
  
              });
            }
  
            if( params.op === 'updateMany' ){
  
              consolelog( rnd, "CASE #2 (updateMany)", params.op );
  
              // Sorry, can't. MongoDb bug #1243
              if( nestedParams.type === 'multiple' ){
                return cb( new Error("You cannot do a mass update of a table that has a father table with 1:n relationship with it. Ask Mongo people to fix https://jira.mongodb.org/browse/SERVER-1243, or this is un`able") );
              }
  
              // The rest is untested and untestable code (not till #1243 is solved)
  
              // Assign the parameters
              filters = params.filters;
              updateObject = params.updateObject;
              unsetObject = params.unsetObject;
  
              // Make up parameters from the passed filters
              try {
                mongoParameters = parentLayer._makeMongoParameters( filters, field );
                // var mongoParameters = parentLayer._makeMongoParameters( filters );
              } catch( e ){
                return cb( e );
              }
  
              consolelog( rnd,  "mongoParameters:" );
              consolelog( mongoParameters.querySelector );
  
              prefix = '_children.' + field + ( nestedParams.type === 'multiple' ?  '.$.' : '.' );
  
              // Make up relative update objects based on the original ones,
              // with extra path added
              relativeUpdateObject = {};
              for( k in updateObject ){
                if( !updateObject.hasOwnProperty( k ) ) continue;
                relativeUpdateObject[ prefix + k ] = updateObject[ k ];
              }
              relativeUnsetObject = {};
              for( k in unsetObject ){
                if( !unsetObject.hasOwnProperty( k ) ) continue;
                relativeUnsetObject[ prefix + k ] = unsetObject[ k ];
              }
  
              consolelog( rnd,  "updateObject:" );
              consolelog( relativeUpdateObject );
  
              var u = { $set: relativeUpdateObject };
              if( Object.keys( relativeUnsetObject ).length ) u.$unset = relativeUnsetObject;
              parentLayer.collection.update( mongoParameters.querySelector, u, { multi: true }, function( err, total ){
                if( err ) return cb( err );
  
                consolelog( rnd, "Updated:", total, "records" );
  
                return cb( null );
              });
            }
  
          // CASE #3 -- DELETE
          } else if( params.op === 'deleteOne' || params.op === 'deleteMany' ){
  
            if( params.op === 'deleteOne' ){
  
              consolelog( rnd, "CASE #3 (deleteOne)", params.op );
  
              // Assign the parameters
              id = params.id;
  
              updateObject = {};
  
              selector = {};
              selector[ '_children.' + field + "." + self.idProperty ] = id;
              selector._clean = true;
  
              // It's a lookup field: it will assign an empty object
              if( nestedParams.type === 'lookup' ){
                updateObject.$set = {};
                updateObject.$set[ '_children.' + field ] = {};
  
              // It's a multiple one: it will $pull the element out
              } else {
                updateObject.$pull = {};
  
                var pullData = {};
                pullData[ self.idProperty  ] =  id ;
                updateObject.$pull[ '_children.' + field ] = pullData;
              }
  
              consolelog( rnd, "Selector:");
              consolelog( selector );
              consolelog( rnd, "UpdateObject:");
              consolelog( updateObject );
  
              parentLayer.collection.update( selector, updateObject, { multi: true }, function( err, total ){
                if( err ) return cb( err );
  
                consolelog( rnd, "Deleted", total, "sub-records" );
  
                return cb( null );
  
              });
            }
  
            if( params.op === 'deleteMany' ){
  
              consolelog( rnd, "CASE #3 (deleteMany)", params.op );
  
              // Assign the parameters
              filters = params.filters;
  
              consolelog("Making filter...", filters, field );
  
              // Make up parameters from the passed filters
              try {
                mongoParameters = parentLayer._makeMongoParameters( filters, field );
              } catch( e ){
                return cb( e );
              }
              selector = { $and: [ { _clean: true }, mongoParameters.querySelector ] };
  
              // Make up parameters from the passed filters
              var mongoParametersForPull;
              try {
                mongoParametersForPull = parentLayer._makeMongoParameters( filters, field, true );
              } catch( e ){
                return cb( e );
              }
  
              consolelog("mongoParameters:", mongoParameters );
              consolelog("mongoParametersForPull:", mongoParametersForPull );
  
              // The update object will depend on whether it's a push or a pull
              updateObject = {};
  
              // It's a lookup field: it will assign an empty object
              if( nestedParams.type === 'lookup' ){
  
                consolelog("It's a lookup!");
  
                updateObject.$set = {};
                updateObject.$set[ '_children.' + field ] = {};
  
                consolelog("Query Selector:", mongoParameters.querySelector );
                consolelog("Update object:", updateObject );
  
                parentLayer.collection.update( selector, updateObject, { multi: true }, function( err, total ){
                  if( err ) return cb( err );
                  consolelog( rnd, "deleted", total, "sub-records" );
  
                  return cb( null );
                });
  
              // It's a multiple one: it will $pull the elementS (with an S, plural) out
              } else {
  
                consolelog("It's a multiple!");
  
                updateObject.$pull = {};
                updateObject.$pull[ '_children.' + field ] = mongoParametersForPull.querySelector;
  
                consolelog("Query Selector:", mongoParameters.querySelector );
                consolelog("Update object:", updateObject );
  
                parentLayer.collection.update( mongoParameters.querySelector, updateObject, { multi: true }, function( err, total ){
                  if( err ) return cb( err );
                  consolelog( rnd, "deleted", total, "sub-records" );
  
                  return cb( null );
                });
              }
  
            }
  
          // CASE #? -- This mustn't happen!
          } else {
            consolelog( rnd, "WARNING?!? params.op and nestedParams.type are:", params.op, nestedParams.type );
  
            cb( null );
          }
  
        },
  
        function( err ){
          if( err ) return cb( err );
          consolelog( rnd, "EXIT: End of function ( _updateParentsRecords)" );
          cb( null );
        }
      );
  
    }