protected function _init() {
		$hosts = [];
		foreach ((array) $this->_config['host'] as $host) {
			$host = HostString::parse($host) + [
				'host' => static::DEFAULT_HOST,
				'port' => static::DEFAULT_PORT
			];
			$hosts[] = "{$host['host']}:{$host['port']}";
		}
		if ($this->_config['login']) {
			$this->_config['dsn'] = sprintf(
				'mongodb://%s:%s@%s/%s',
				$this->_config['login'],
				$this->_config['password'],
				implode(',', $hosts),
				$this->_config['database']
			);
		} else {
			$this->_config['dsn'] = sprintf(
				'mongodb://%s',
				implode(',', $hosts)
			);
		}
		parent::_init();

		$this->_operators += [
			'like' => function($key, $value) {
				return new MongoRegex($value);
			},
			'$exists' => function($key, $value) {
				return ['$exists' => (boolean) $value];
			},
			'$type' => function($key, $value) {
				return ['$type' => (integer) $value];
			},
			'$mod' => function($key, $value) {
				$value = (array) $value;
				return ['$mod' => [current($value), next($value) ?: 0]];
			},
			'$size' => function($key, $value) {
				return ['$size' => (integer) $value];
			},
			'$elemMatch' => function($operator, $values, $options = []) {
				$options += [
					'castOpts' => [],
					'field' => ''
				];
				$options['castOpts'] += ['pathKey' => $options['field']];
				$values = (array) $values;

				if (empty($options['castOpts']['schema'])) {
					return ['$elemMatch' => $values];
				}
				foreach ($values as $key => &$value) {
					$value = $options['castOpts']['schema']->cast(
						null, $key, $value, $options['castOpts']
					);
				}
				return ['$elemMatch' => $values];
			}
		];
	}