protected static function _update($export) {
		$export += [
			'data' => [],
			'update' => [],
			'remove' => [],
			'rename' => [],
			'key' => ''
		];
		$path = $export['key'] ? "{$export['key']}." : "";
		$result = ['update' => [], 'remove' => []];
		$left = static::_diff($export['data'], $export['update']);
		$right = static::_diff($export['update'], $export['data']);

		$objects = array_filter($export['update'], function($value) {
			return (is_object($value) && method_exists($value, 'export'));
		});
		array_map(function($key) use (&$left) { unset($left[$key]); }, array_keys($right));

		foreach ($left as $key => $value) {
			$result = static::_append($result, "{$path}{$key}", $value, 'remove');
		}
		$update = $right + $objects;

		foreach ($update as $key => $value) {
			$original = $export['data'];
			$isArray = is_object($value) && $value instanceof static::$_classes['set'];

			$options = [
				'indexed' => null,
				'handlers' => [
					'MongoDate' => function($value) { return $value; },
					'MongoId' => function($value) { return $value; }
				]
			];

			if ($isArray) {
				$newValue = $value->to('array', $options);
				$originalValue = null;
				$shouldConvert = (isset($original[$key]) && (
					$original[$key] instanceof static::$_classes['set'] ||
					$original[$key] instanceof static::$_classes['entity']
				));
				if ($shouldConvert) {
					$originalValue = $original[$key]->to('array', $options);
				}
				if ($newValue !== $originalValue) {
					$value = $newValue;
				}
			}
			$result = static::_append($result, "{$path}{$key}", $value, 'update');
		}
		return array_filter($result);
	}
protected static function _update($export) {
		$export += [
			'data' => [],
			'update' => [],
			'remove' => [],
			'rename' => [],
			'key' => ''
		];
		$path = $export['key'] ? "{$export['key']}." : "";
		$result = ['update' => [], 'remove' => []];
		$left = static::_diff($export['data'], $export['update']);
		$right = static::_diff($export['update'], $export['data']);

		$objects = array_filter($export['update'], function($value) {
			return (is_object($value) && method_exists($value, 'export'));
		});
		array_map(function($key) use (&$left) { unset($left[$key]); }, array_keys($right));

		foreach ($left as $key => $value) {
			$result = static::_append($result, "{$path}{$key}", $value, 'remove');
		}
		$update = $right + $objects;

		foreach ($update as $key => $value) {
			$original = $export['data'];
			$isArray = is_object($value) && $value instanceof static::$_classes['set'];

			$options = [
				'indexed' => null,
				'handlers' => [
					'MongoDate' => function($value) { return $value; },
					'MongoId' => function($value) { return $value; }
				]
			];

			if ($isArray) {
				$newValue = $value->to('array', $options);
				$originalValue = null;
				$shouldConvert = (isset($original[$key]) && (
					$original[$key] instanceof static::$_classes['set'] ||
					$original[$key] instanceof static::$_classes['entity']
				));
				if ($shouldConvert) {
					$originalValue = $original[$key]->to('array', $options);
				}
				if ($newValue !== $originalValue) {
					$value = $newValue;
				}
			}
			$result = static::_append($result, "{$path}{$key}", $value, 'update');
		}
		return array_filter($result);
	}
protected static function _update ( $ export ) { $ export += [ 'data' => [ ] , 'update' => [ ] , 'remove' => [ ] , 'rename' => [ ] , 'key' => '' ] ; $ path = $ export [ 'key' ] ? "{$export['key']}." : "" ; $ result = [ 'update' => [ ] , 'remove' => [ ] ] ; $ left = static :: _diff ( $ export [ 'data' ] , $ export [ 'update' ] ) ; $ right = static :: _diff ( $ export [ 'update' ] , $ export [ 'data' ] ) ; $ objects = array_filter ( $ export [ 'update' ] , function ( $ value ) { return ( is_object ( $ value ) && method_exists ( $ value , 'export' ) ) ; } ) ; array_map ( function ( $ key ) use ( & $ left ) { unset ( $ left [ $ key ] ) ; } , array_keys ( $ right ) ) ; foreach ( $ left as $ key => $ value ) { $ result = static :: _append ( $ result , "{$path}{$key}" , $ value , 'remove' ) ; } $ update = $ right + $ objects ; foreach ( $ update as $ key => $ value ) { $ original = $ export [ 'data' ] ; $ isArray = is_object ( $ value ) && $ value instanceof static :: $ _classes [ 'set' ] ; $ options = [ 'indexed' => null , 'handlers' => [ 'MongoDate' => function ( $ value ) { return $ value ; } , 'MongoId' => function ( $ value ) { return $ value ; } ] ] ; if ( $ isArray ) { $ newValue = $ value -> to ( 'array' , $ options ) ; $ originalValue = null ; $ shouldConvert = ( isset ( $ original [ $ key ] ) && ( $ original [ $ key ] instanceof static :: $ _classes [ 'set' ] || $ original [ $ key ] instanceof static :: $ _classes [ 'entity' ] ) ) ; if ( $ shouldConvert ) { $ originalValue = $ original [ $ key ] -> to ( 'array' , $ options ) ; } if ( $ newValue !== $ originalValue ) { $ value = $ newValue ; } } $ result = static :: _append ( $ result , "{$path}{$key}" , $ value , 'update' ) ; } return array_filter ( $ result ) ; }
Calculates changesets for update operations, and produces an array which can be converted to
a set of native MongoDB update operations.

@todo Implement remove and rename.
@param array $export An array of fields exported from a call to `Document::export()`, and
should contain the following keys:
- `'data'` _array_: An array representing the original data loaded from the
database for the document.
- `'update'` _array_: An array representing the current state of the document,
containing any modifications made.
- `'key'` _string_: If this is a nested document, this is a dot-separated path
from the root-level document.
@return array Returns an array representing the changes to be made to the document. These
are converted to database-native commands by the `toCommand()` method.
Calculates changesets for update operations and produces an array which can be converted to a set of native MongoDB update operations .