得到某个字段的值
@access public
@param  Query     $query     查询对象
@param  string    $aggregate 聚合方法
@param  string    $field     字段名
@return mixed
354988
public function aggregate(Query $query, $aggregate, $field)
    {
        if (is_string($field) && 0 === stripos($field, 'DISTINCT ')) {
            list($distinct, $field) = explode(' ', $field);
        }

        $field = $aggregate . '(' . (!empty($distinct) ? 'DISTINCT ' : '') . $this->builder->parseKey($query, $field, true) . ') AS tp_' . strtolower($aggregate);

        return $this->value($query, $field, 0);
    }
930566
public function executeUpdate(MongoCollection $collection, Query $query) {
        $where = $this->formatWhere($query->getWhere());
        $fields = $this->formatFields($query);

        $query->attribute([
            'upsert' => false,
            'multiple' => ($query->getLimit() != 1) // multiple in PHP, multi in Mongo
        ]);

        $response = $collection->update($where, $fields, $query->getAttributes() + ['w' => 1]);
        $response['params'] = [
            'where' => $where,
            'fields' => $fields
        ];

        return $response;
    }
701286
public function executeDropIndex(MongoCollection $collection, Query $query) {
        $fields = $this->formatFields($query);

        $response = $collection->deleteIndex($fields, $query->getAttributes() + ['w' => 1]);
        $response['params'] = [
            'fields' => $fields
        ];

        return $response;
    }
303418
public function query($entity, $query)
	{
		$retValue = array();

		if (! is_null($this->_db)){
			try{
				$mongo = $this->_db->selectCollection($entity);

				// Find by query
				$cursor = $mongo->find($query);

				if (is_null($cursor))
					$retValue = array();
				else
					$retValue = iterator_to_array($cursor);
			}
			catch(Exception $e) {
				$this->_log->addError($e->getMessage());
			}	
		}

		return $retValue;
	}
1146192
public function select(Query $query)
    {
        $options = $query->getOptions();

        return str_replace(
            ['%TABLE%', '%DISTINCT%', '%FIELD%', '%JOIN%', '%WHERE%', '%GROUP%', '%HAVING%', '%ORDER%', '%LIMIT%', '%UNION%', '%LOCK%', '%COMMENT%', '%FORCE%'],
            [
                $this->parseTable($query, $options['table']),
                $this->parseDistinct($query, $options['distinct']),
                $this->parseField($query, $options['field']),
                $this->parseJoin($query, $options['join']),
                $this->parseWhere($query, $options['where']),
                $this->parseGroup($query, $options['group']),
                $this->parseHaving($query, $options['having']),
                $this->parseOrder($query, $options['order']),
                $this->parseLimit($query, $options['limit']),
                $this->parseUnion($query, $options['union']),
                $this->parseLock($query, $options['lock']),
                $this->parseComment($query, $options['comment']),
                $this->parseForce($query, $options['force']),
            ],
            $this->selectSql);
    }
560248
protected function _schema($query, $fields = null) {
		$model = $query->model();
		$paths = $query->paths($this);
		$models = $query->models($this);
		$alias = $query->alias();
		$result = [];

		if (!$model) {
			foreach ($fields as $field => $value) {
				if (is_array($value)) {
					$result[$field] = array_keys($value);
				} else {
					$result[''][] = $field;
				}
			}
			return $result;
		}
		if (!$fields) {
			foreach ($paths as $alias => $relation) {
				$model = $models[$alias];
				$result[$relation] = $model::schema()->names();
			}
			return $result;
		}

		$unalias = function ($value) {
			if (is_object($value) && isset($value->scalar)) {
				$value = $value->scalar;
			}
			$aliasing = preg_split("/\s+as\s+/i", $value);
			return isset($aliasing[1]) ? $aliasing[1] : $value;
		};

		if (isset($fields[0])) {
			$raw = array_map($unalias, $fields[0]);
			unset($fields[0]);
		}

		$fields = isset($fields[$alias]) ? [$alias => $fields[$alias]] + $fields : $fields;

		foreach ($fields as $field => $value) {
			if (is_array($value)) {
				if (isset($value['*'])) {
					$relModel = $models[$field];
					$result[$paths[$field]] = $relModel::schema()->names();
				} else {
					$result[$paths[$field]] = array_map($unalias, array_keys($value));
				}
			}
		}

		if (isset($raw)) {
			$result[''] = isset($result['']) ? array_merge($raw, $result['']) : $raw;
		}
		return $result;
	}
934500
public function findOne(array $query = [], array $fields = [])
    {
        if ($this->eventManager->hasListeners(Events::preFindOne)) {
            $findEventArgs = new FindEventArgs($this, $query, $fields);
            $this->eventManager->dispatchEvent(Events::preFindOne, $findEventArgs);
            $query = $findEventArgs->getQuery();
            $fields = $findEventArgs->getFields();
        }

        $result = $this->doFindOne($query, $fields);

        if ($this->eventManager->hasListeners(Events::postFindOne)) {
            $eventArgs = new MutableEventArgs($this, $result);
            $this->eventManager->dispatchEvent(Events::postFindOne, $eventArgs);
            $result = $eventArgs->getData();
        }

        return $result;
    }
89983
public function withAvg($relation, $field, $subQuery = true)
    {
        return $this->withAggregate($relation, 'avg', $field, $subQuery);
    }
284964
public function column(Query $query, $field, $key = '')
    {
        $options = $query->getOptions();
        $result  = false;
        if ($this->cache && !empty($options['cache'])) {
            // 判断查询缓存
            $cache  = $options['cache'];
            $guid   = is_string($cache['key']) ? $cache['key'] : md5($field . serialize($options));
            $result = $this->cache->get($guid);
        }

        if (!$result) {
            if (isset($options['projection'])) {
                $query->removeOption('projection');
            }

            if ($key && '*' != $field) {
                $field = $key . ',' . $field;
            }

            if (is_string($field)) {
                $field = array_map('trim', explode(',', $field));
            }

            $query->field($field);

            $mongoQuery = $this->builder->select($query);
            // 执行查询操作
            $readPreference = isset($options['readPreference']) ? $options['readPreference'] : null;
            $cursor         = $this->query($options['table'], $mongoQuery, $readPreference, true, ['root' => 'array']);
            $resultSet      = $cursor->toArray();

            if ($resultSet) {
                $fields = array_keys(get_object_vars($resultSet[0]));
                $count  = count($fields);
                $key1   = array_shift($fields);
                $key2   = $fields ? array_shift($fields) : '';
                $key    = $key ?: $key1;

                foreach ($resultSet as $val) {
                    $val = (array) $val;
                    if ($this->getConfig('pk_convert_id')) {
                        // 转换ObjectID 字段
                        $val['id'] = $val['_id']->__toString();
                        unset($val['_id']);
                    }
                    $name = $val[$key];

                    if (2 == $count) {
                        $result[$name] = $val[$key2];
                    } elseif (1 == $count) {
                        $result[$name] = $val[$key1];
                    } else {
                        $result[$name] = $val;
                    }
                }
            } else {
                $result = [];
            }

            if (isset($cache) && isset($guid)) {
                // 缓存数据
                $this->cacheData($guid, $result, $cache);
            }
        }

        return $result;
    }
1181662
def _aggop(self, query):
        
        if isinstance(query.select, list):
            # RETURN SINGLE OBJECT WITH AGGREGATES
            for s in query.select:
                if s.aggregate not in aggregates:
                    Log.error("Expecting all columns to have an aggregate: {{select}}", select=s)

            selects = FlatList()
            for s in query.select:
                selects.append(sql_alias(aggregates[s.aggregate].replace("{{code}}", s.value),quote_column(s.name)))

            sql = expand_template("""
                SELECT
                    {{selects}}
                FROM
                    {{table}}
                {{where}}
            """, {
                "selects": SQL(",\n".join(selects)),
                "table": self._subquery(query["from"])[0],
                "where": self._where2sql(query.filter)
            })

            return sql, lambda sql: self.db.column(sql)[0]  # RETURNING SINGLE OBJECT WITH AGGREGATE VALUES
        else:
            # RETURN SINGLE VALUE
            s0 = query.select
            if s0.aggregate not in aggregates:
                Log.error("Expecting all columns to have an aggregate: {{select}}", select=s0)

            select = sql_alias(aggregates[s0.aggregate].replace("{{code}}", s0.value) , quote_column(s0.name))

            sql = expand_template("""
                SELECT
                    {{selects}}
                FROM
                    {{table}}
                {{where}}
            """, {
                "selects": SQL(select),
                "table": self._subquery(query["from"])[0],
                "where": self._where2sql(query.where)
            })

            def post(sql):
                result = self.db.column_query(sql)
                return result[0][0]

            return sql, post
793274
private function buildAggQueryData($query)
    {
        $ret = [];

        foreach ($this->aggregations as $agg) {
            $additions = $agg->buildQueryData($this, $query);
            if ($additions) {
                $ret = array_merge($ret, $additions);
            }
        }

        return $ret;
    }
1084995
public function aggregate($aggregate, $field, $force = false)
    {
        $this->parseOptions();

        $result = $this->cmd('aggregate', [strtolower($aggregate), $field]);
        $value  = isset($result[0]['aggregate']) ? $result[0]['aggregate'] : 0;

        if ($force) {
            $value += 0;
        }

        return $value;
    }
689630
private function prepare($query)
    {
        foreach ($this->aggregations as $agg) {
            $agg->prepareQuery($this, $query);
        }

        // Handle paging
        $this->setPage(
            $this->getQueryParam($query, $this->pageParameterName, 0)
                + $this->pageDelta
        );
    }
814604
public function getRelationCountQuery($closure, $aggregate = 'count', $field = '*')
    {
        if ($closure) {
            $closure($this->query);
        }

        return $this->query
            ->whereExp($this->foreignKey, '=' . $this->parent->getTable() . '.' . $this->parent->getPk())
            ->fetchSql()
            ->$aggregate($field);
    }
1074854
protected function parseIn(Query $query, $key, $exp, $value, $field, $bindType)
    {
        // IN 查询
        if ($value instanceof \Closure) {
            $value = $this->parseClosure($query, $value, false);
        } else {
            $value = array_unique(is_array($value) ? $value : explode(',', $value));

            $array = [];

            foreach ($value as $k => $v) {
                $name    = $query->bind($v, $bindType);
                $array[] = ':' . $name;
            }

            $zone = implode(',', $array);

            $value = empty($zone) ? "''" : $zone;
        }

        return $key . ' ' . $exp . ' (' . $value . ')';
    }
757594
public function select($field = null, $where = null, $order = null, $limit = null)
    {
        //如果未提供条件/排序/分页参数
        if (!$where and !$order and !$limit) {
            //并且未提供字段参数,则表明是之前已经提供,现在要真正执行
            if (!$field) {
                return $this->go();
            }

            //只提供了字段, 并不真正执行, 这里很诡异
            return $this->fields($field);
        }
        //提供了多项,则,设置并执行
        $result = parent::selectArray($field, $where, $order, $limit);
        return new Result($this->tableName, $result);
    }
731101
public function aggregate($aggregation = [])
    {
        if ($aggregation instanceof Closure) {
            // Store the callback
            $callback = $aggregation;

            // Create a new pipeline
            $aggregation = new Query\Aggregation();

            // Fire the callback
            $callback($aggregation);
        }

        if ($aggregation instanceof Query\Aggregation) {
            // Retrieve the pipeline
            $aggregation = $aggregation->getPipeline();
        }

        // Execute the aggregation.
        return $this->collection->aggregate($aggregation);
    }