diff --git a/apps/advanced/common/models/User.php b/apps/advanced/common/models/User.php
index 6f43b28..b1cf75f 100644
--- a/apps/advanced/common/models/User.php
+++ b/apps/advanced/common/models/User.php
@@ -69,7 +69,7 @@ class User extends ActiveRecord implements IdentityInterface
     /**
      * @inheritdoc
      */
-    public static function findIdentityByAccessToken($token)
+    public static function findIdentityByAccessToken($token, $type = null)
     {
         throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
     }
diff --git a/apps/basic/models/User.php b/apps/basic/models/User.php
index 5de7e20..cbfb9fe 100644
--- a/apps/basic/models/User.php
+++ b/apps/basic/models/User.php
@@ -38,7 +38,7 @@ class User extends \yii\base\Object implements \yii\web\IdentityInterface
     /**
      * @inheritdoc
      */
-    public static function findIdentityByAccessToken($token)
+    public static function findIdentityByAccessToken($token, $type = null)
     {
         foreach (self::$users as $user) {
             if ($user['accessToken'] === $token) {
diff --git a/docs/guide/rest-quick-start.md b/docs/guide/rest-quick-start.md
index ee44edd..2da13e9 100644
--- a/docs/guide/rest-quick-start.md
+++ b/docs/guide/rest-quick-start.md
@@ -679,7 +679,7 @@ use yii\web\IdentityInterface;
 
 class User extends ActiveRecord implements IdentityInterface
 {
-    public static function findIdentityByAccessToken($token)
+    public static function findIdentityByAccessToken($token, $type = null)
     {
         return static::findOne(['access_token' => $token]);
     }
diff --git a/docs/guide/security-authentication.md b/docs/guide/security-authentication.md
index 7f24c9b..fb9cd0f 100644
--- a/docs/guide/security-authentication.md
+++ b/docs/guide/security-authentication.md
@@ -32,7 +32,7 @@ class User extends ActiveRecord implements IdentityInterface
      * @param string $token the token to be looked for
      * @return IdentityInterface|null the identity object that matches the given token.
      */
-    public static function findIdentityByAccessToken($token)
+    public static function findIdentityByAccessToken($token, $type = null)
     {
         return static::findOne(['access_token' => $token]);
     }
diff --git a/docs/guide/security-authorization.md b/docs/guide/security-authorization.md
index d9bc358..9a75411 100644
--- a/docs/guide/security-authorization.md
+++ b/docs/guide/security-authorization.md
@@ -460,7 +460,7 @@ of the rule class, you need to respect this hierarchy as well. That is why when 
 the `execute()` method will return true if the user group is either 1 or 2 (meaning the user is in either "admin"
 group or "author" group).
 
-Next, configure `authManager` by listing the two roles in [[yii\rbac\ManagerInterface::defaultRoles]]:
+Next, configure `authManager` by listing the two roles in [[yii\rbac\BaseManager::$defaultRoles]]:
 
 ```php
 return [
diff --git a/docs/guide/start-basic.md b/docs/guide/start-installation.md
similarity index 54%
rename from docs/guide/start-basic.md
rename to docs/guide/start-installation.md
index e02ad70..6d52276 100644
--- a/docs/guide/start-basic.md
+++ b/docs/guide/start-installation.md
@@ -1,5 +1,85 @@
-Basic application template
-==========================
+Installing Yii
+==============
+
+There are two ways to install Yii:
+
+* Using [Composer](http://getcomposer.org/);
+* Downloading an archive file from [yiiframework.com](http://www.yiiframework.com/download/).
+
+The first approach is highly recommended, as it allows you to automatically install updates
+
+
+Installing via Composer
+-----------------------
+
+The recommended way to install Yii is to use the [Composer](http://getcomposer.org/) package manager. If you do not already
+have Composer installed, you may download it from [http://getcomposer.org/](http://getcomposer.org/), or run the following command to download and install it:
+
+```
+curl -s http://getcomposer.org/installer | php
+```
+
+(It is strongly recommended to perform a [global Composer installation](https://getcomposer.org/doc/00-intro.md#globally)).
+
+For problems with, or more information on, installing Composer, see the official Composer guide:
+
+* [Linux](http://getcomposer.org/doc/00-intro.md#installation-nix)
+* [Windows](http://getcomposer.org/doc/00-intro.md#installation-windows)
+
+With Composer installed, you can create a new Yii site using one of Yii's ready-to-use application templates. Based on your needs, choosing the right template can help bootstrap your project.
+
+Currently, there are two Yii application templates available:
+
+- [Basic Application Template](https://github.com/yiisoft/yii2-app-basic), a basic frontend application template
+- [Advanced Application Template](https://github.com/yiisoft/yii2-app-advanced), consisting of a frontend, a backend, console resources, common (shared code), and support for environments
+
+For template installation instructions, see the above linked pages.
+To read more about the ideas behind these application templates and the proposed usage,
+refer to the [basic application template](apps-basic.md) and [advanced application template](apps-advanced.md) documents.
+
+If you do not want to use a template, rather starting from scratch, you'll find information in the [creating your own application structure](apps-own.md) document. This approach is only recommended for advanced users.
+
+
+Installing from zip
+-------------------
+
+Installation from a zip file involves two steps:
+
+   1. Downloading an application template from [yiiframework.com](http://www.yiiframework.com/download/).
+   2. Unpacking the downloaded file.
+
+If you only want the Yii Framework files you can download a zip file directly from [github](https://github.com/yiisoft/yii2-framework/releases).
+To create your application you might want to follow the steps described in [creating your own application structure](apps-own.md).
+This is only recommended for advanced users.
+
+> Tip: The Yii framework itself does not need to be installed under a web-accessible directory (in fact, it should not be).
+A Yii application has one entry script, which is usually the only file that absolutely must be
+exposed to web users (i.e., placed within the web directory). Other PHP scripts, including those
+in the Yii Framework, should be protected from web access to prevent possible exploitation by hackers.
+
+
+Requirements
+------------
+
+Yii 2 requires PHP 5.4.0 or higher. Yii has been tested with the [Apache HTTP server](http://httpd.apache.org/) and
+[Nginx HTTP server](http://nginx.org/) on both Windows and Linux.
+Yii may also be usable on other web servers and platforms, provided that PHP 5.4 or higher is present.
+
+After installing Yii, you may want to verify that your server satisfies
+Yii's requirements. You can do so by running the requirement checker
+script in a web browser or from the command line.
+
+If you have installed a Yii application template via the downloaded zip file or Composer, you'll find a `requirements.php` file in the
+base directory of your application.
+
+In order to run this script on the command line use the following command (after navigating to the directory where `requirements.php` can be found):
+
+```
+php requirements.php
+```
+
+In order to run this script in your browser, you must make sure it's within a web directory, and then
+access `http://hostname/path/to/yii-app/requirements.php` in your browser.
 
 > Note: This section is under development.
 
diff --git a/extensions/apidoc/models/BaseDoc.php b/extensions/apidoc/models/BaseDoc.php
index 7e1ed94..c20d9c9 100644
--- a/extensions/apidoc/models/BaseDoc.php
+++ b/extensions/apidoc/models/BaseDoc.php
@@ -42,6 +42,26 @@ class BaseDoc extends Object
      */
     public $tags = [];
 
+    public function hasTag($name)
+    {
+        foreach ($this->tags as $tag) {
+            if (strtolower($tag->getName()) == $name) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public function removeTag($name)
+    {
+        foreach ($this->tags as $i => $tag) {
+            if (strtolower($tag->getName()) == $name) {
+                unset($this->tags[$i]);
+            }
+        }
+    }
+
+
     /**
      * @param \phpDocumentor\Reflection\BaseReflector $reflector
      * @param Context $context
@@ -70,7 +90,7 @@ class BaseDoc extends Object
                     'message' => "No short description for " . substr(StringHelper::basename(get_class($this)), 0, -3) . " '{$this->name}'",
                 ];
             }
-            $this->description = $docblock->getLongDescription();
+            $this->description = $docblock->getLongDescription()->getContents();
 
             $this->phpDocContext = $docblock->getContext();
 
diff --git a/extensions/apidoc/models/Context.php b/extensions/apidoc/models/Context.php
index 351f96e..ea584a4 100644
--- a/extensions/apidoc/models/Context.php
+++ b/extensions/apidoc/models/Context.php
@@ -164,11 +164,33 @@ class Context extends Component
     {
         // TODO also for properties?
         foreach ($class->methods as $m) {
-            $inheritedMethod = $this->inheritMethodRecursive($m, $class);
-            foreach (['shortDescription', 'description', 'params', 'return', 'returnType', 'returnTypes', 'exceptions'] as $property) {
-                if (empty($m->$property)) {
-                    $m->$property = $inheritedMethod->$property;
+            if ($m->hasTag('inheritdoc')) {
+                $inheritedMethod = $this->inheritMethodRecursive($m, $class);
+                foreach (['shortDescription', 'description', 'return', 'returnType', 'returnTypes', 'exceptions'] as $property) {
+                    if (empty($m->$property) || is_string($m->$property) && trim($m->$property) === '') {
+                        $m->$property = $inheritedMethod->$property;
+                    }
                 }
+                foreach ($m->params as $i => $param) {
+                    if (!isset($inheritedMethod->params[$i])) {
+                        $this->errors[] = [
+                            'line' => $m->startLine,
+                            'file' => $class->sourceFile,
+                            'message' => "Method param $i does not exist in parent method, @inheritdoc not possible in {$m->name} in {$class->name}.",
+                        ];
+                        continue;
+                    }
+                    if (empty($param->description) || trim($param->description) === '') {
+                        $param->description = $inheritedMethod->params[$i]->description;
+                    }
+                    if (empty($param->type) || trim($param->type) === '') {
+                        $param->type = $inheritedMethod->params[$i]->type;
+                    }
+                    if (empty($param->types) || trim($param->types) === '') {
+                        $param->types = $inheritedMethod->params[$i]->types;
+                    }
+                }
+                $m->removeTag('inheritdoc');
             }
         }
     }
@@ -179,20 +201,50 @@ class Context extends Component
      */
     private function inheritMethodRecursive($method, $class)
     {
-        if (!isset($this->classes[$class->parentClass])) {
-            return $method;
-        }
-        $parent = $this->classes[$class->parentClass];
-        foreach ($method->tags as $tag) {
-            if (strtolower($tag->getName()) == 'inheritdoc') {
-                if (isset($parent->methods[$method->name])) {
-                    $method = $parent->methods[$method->name];
+        $inheritanceCandidates = array_merge(
+            $this->getParents($class),
+            $this->getInterfaces($class)
+        );
+
+        $methods = [];
+        foreach($inheritanceCandidates as $candidate) {
+            if (isset($candidate->methods[$method->name])) {
+                $cmethod = $candidate->methods[$method->name];
+                if ($cmethod->hasTag('inheritdoc')) {
+                    $this->inheritDocs($candidate);
                 }
+                $methods[] = $cmethod;
+            }
+        }
 
-                return $this->inheritMethodRecursive($method, $parent);
+        return reset($methods);
+    }
+
+    /**
+     * @param ClassDoc $class
+     * @return array
+     */
+    private function getParents($class)
+    {
+        if ($class->parentClass === null || !isset($this->classes[$class->parentClass])) {
+            return [];
+        }
+        return array_merge([$this->classes[$class->parentClass]], $this->getParents($this->classes[$class->parentClass]));
+    }
+
+    /**
+     * @param ClassDoc $class
+     * @return array
+     */
+    private function getInterfaces($class)
+    {
+        $interfaces = [];
+        foreach($class->interfaces as $interface) {
+            if (isset($this->interfaces[$interface])) {
+                $interfaces[] = $this->interfaces[$interface];
             }
         }
-        return $method;
+        return $interfaces;
     }
 
     /**
diff --git a/extensions/elasticsearch/ActiveQuery.php b/extensions/elasticsearch/ActiveQuery.php
index 4fb02ff..499eccc 100644
--- a/extensions/elasticsearch/ActiveQuery.php
+++ b/extensions/elasticsearch/ActiveQuery.php
@@ -7,6 +7,7 @@
 
 namespace yii\elasticsearch;
 
+use yii\base\NotSupportedException;
 use yii\db\ActiveQueryInterface;
 use yii\db\ActiveQueryTrait;
 use yii\db\ActiveRelationTrait;
@@ -143,47 +144,21 @@ class ActiveQuery extends Query implements ActiveQueryInterface
      */
     public function all($db = null)
     {
+        if ($this->asArray) {
+            // TODO implement with
+            return parent::all($db);
+        }
+
         $result = $this->createCommand($db)->search();
         if (empty($result['hits']['hits'])) {
             return [];
         }
-        if ($this->fields !== null) {
-            foreach ($result['hits']['hits'] as &$row) {
-                $row['_source'] = isset($row['fields']) ? $row['fields'] : [];
-                unset($row['fields']);
-            }
-            unset($row);
-        }
-        /** @var ActiveRecord $modelClass */
-        $modelClass = $this->modelClass;
-        $pk = $modelClass::primaryKey()[0];
-        if ($this->asArray && $this->indexBy) {
-            foreach ($result['hits']['hits'] as &$row) {
-                if ($pk === '_id') {
-                    $row['_source']['_id'] = $row['_id'];
-                }
-                $row['_source']['_score'] = $row['_score'];
-                $row = $row['_source'];
-            }
-            unset($row);
-        }
         $models = $this->createModels($result['hits']['hits']);
-        if ($this->asArray && !$this->indexBy) {
-            foreach ($models as $key => $model) {
-                if ($pk === '_id') {
-                    $model['_source']['_id'] = $model['_id'];
-                }
-                $model['_source']['_score'] = $model['_score'];
-                $models[$key] = $model['_source'];
-            }
-        }
         if (!empty($this->with)) {
             $this->findWith($this->with, $models);
         }
-        if (!$this->asArray) {
-            foreach ($models as $model) {
-                $model->afterFind();
-            }
+        foreach ($models as $model) {
+            $model->afterFind();
         }
 
         return $models;
@@ -203,30 +178,34 @@ class ActiveQuery extends Query implements ActiveQueryInterface
             return null;
         }
         if ($this->asArray) {
-            /** @var ActiveRecord $modelClass */
-            $modelClass = $this->modelClass;
-            $model = $result['_source'];
-            $pk = $modelClass::primaryKey()[0];
-            if ($pk === '_id') {
-                $model['_id'] = $result['_id'];
-            }
-            $model['_score'] = $result['_score'];
+            // TODO implement with
+//            /** @var ActiveRecord $modelClass */
+//            $modelClass = $this->modelClass;
+//            $model = $result['_source'];
+//            $pk = $modelClass::primaryKey()[0];
+//            if ($pk === '_id') {
+//                $model['_id'] = $result['_id'];
+//            }
+//            $model['_score'] = $result['_score'];
+//            if (!empty($this->with)) {
+//                $models = [$model];
+//                $this->findWith($this->with, $models);
+//                $model = $models[0];
+//            }
+            return $result;
         } else {
             /** @var ActiveRecord $class */
             $class = $this->modelClass;
             $model = $class::instantiate($result);
             $class::populateRecord($model, $result);
-        }
-        if (!empty($this->with)) {
-            $models = [$model];
-            $this->findWith($this->with, $models);
-            $model = $models[0];
-        }
-        if (!$this->asArray) {
+            if (!empty($this->with)) {
+                $models = [$model];
+                $this->findWith($this->with, $models);
+                $model = $models[0];
+            }
             $model->afterFind();
+            return $model;
         }
-
-        return $model;
     }
 
     /**
@@ -235,27 +214,14 @@ class ActiveQuery extends Query implements ActiveQueryInterface
     public function search($db = null, $options = [])
     {
         $result = $this->createCommand($db)->search($options);
-        if (!empty($result['hits']['hits'])) {
+        // TODO implement with for asArray
+        if (!empty($result['hits']['hits']) && !$this->asArray) {
             $models = $this->createModels($result['hits']['hits']);
-            if ($this->asArray) {
-                /** @var ActiveRecord $modelClass */
-                $modelClass = $this->modelClass;
-                $pk = $modelClass::primaryKey()[0];
-                foreach ($models as $key => $model) {
-                    if ($pk === '_id') {
-                        $model['_source']['_id'] = $model['_id'];
-                    }
-                    $model['_source']['_score'] = $model['_score'];
-                    $models[$key] = $model['_source'];
-                }
-            }
             if (!empty($this->with)) {
                 $this->findWith($this->with, $models);
             }
-            if (!$this->asArray) {
-                foreach ($models as $model) {
-                    $model->afterFind();
-                }
+            foreach ($models as $model) {
+                $model->afterFind();
             }
             $result['hits']['hits'] = $models;
         }
@@ -266,28 +232,12 @@ class ActiveQuery extends Query implements ActiveQueryInterface
     /**
      * @inheritdoc
      */
-    public function scalar($field, $db = null)
-    {
-        $record = parent::one($db);
-        if ($record !== false) {
-            if ($field == '_id') {
-                return $record['_id'];
-            } elseif (isset($record['_source'][$field])) {
-                return $record['_source'][$field];
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * @inheritdoc
-     */
     public function column($field, $db = null)
     {
         if ($field == '_id') {
             $command = $this->createCommand($db);
             $command->queryParts['fields'] = [];
+            $command->queryParts['_source'] = false;
             $result = $command->search();
             if (empty($result['hits']['hits'])) {
                 return [];
diff --git a/extensions/elasticsearch/ActiveRecord.php b/extensions/elasticsearch/ActiveRecord.php
index b5c1454..6ff1095 100644
--- a/extensions/elasticsearch/ActiveRecord.php
+++ b/extensions/elasticsearch/ActiveRecord.php
@@ -114,7 +114,7 @@ class ActiveRecord extends BaseActiveRecord
         }
         $command = static::getDb()->createCommand();
         $result = $command->get(static::index(), static::type(), $primaryKey, $options);
-        if ($result['exists']) {
+        if ($result['found']) {
             $model = static::instantiate($result);
             static::populateRecord($model, $result);
             $model->afterFind();
@@ -150,7 +150,7 @@ class ActiveRecord extends BaseActiveRecord
         $result = $command->mget(static::index(), static::type(), $primaryKeys, $options);
         $models = [];
         foreach ($result['docs'] as $doc) {
-            if ($doc['exists']) {
+            if ($doc['found']) {
                 $model = static::instantiate($doc);
                 static::populateRecord($model, $doc);
                 $model->afterFind();
@@ -282,8 +282,23 @@ class ActiveRecord extends BaseActiveRecord
      */
     public static function populateRecord($record, $row)
     {
-        parent::populateRecord($record, $row['_source']);
-        $pk = static::primaryKey()[0];
+        $attributes = [];
+        if (isset($row['_source'])) {
+            $attributes = $row['_source'];
+        }
+        if (isset($row['fields'])) {
+            // reset fields in case it is scalar value TODO use field metadata for this
+            foreach($row['fields'] as $key => $value) {
+                if (count($value) == 1) {
+                    $row['fields'][$key] = reset($value);
+                }
+            }
+            $attributes = array_merge($attributes, $row['fields']);
+        }
+
+        parent::populateRecord($record, $attributes);
+
+        $pk = static::primaryKey()[0];//TODO should always set ID in case of fields are not returned
         if ($pk === '_id') {
             $record->_id = $row['_id'];
         }
@@ -379,9 +394,9 @@ class ActiveRecord extends BaseActiveRecord
                 $options
             );
 
-            if (!isset($response['ok'])) {
-                return false;
-            }
+//            if (!isset($response['ok'])) {
+//                return false;
+//            }
             $pk = static::primaryKey()[0];
             $this->$pk = $response['_id'];
             if ($pk != '_id') {
@@ -444,13 +459,13 @@ class ActiveRecord extends BaseActiveRecord
         $n = 0;
         $errors = [];
         foreach ($response['items'] as $item) {
-            if (isset($item['update']['error'])) {
-                $errors[] = $item['update'];
-            } elseif ($item['update']['ok']) {
+            if (isset($item['update']['status']) && $item['update']['status'] == 200) {
                 $n++;
+            } else {
+                $errors[] = $item['update'];
             }
         }
-        if (!empty($errors)) {
+        if (!empty($errors) || isset($response['errors']) && $response['errors']) {
             throw new Exception(__METHOD__ . ' failed updating records.', $errors);
         }
 
@@ -508,13 +523,13 @@ class ActiveRecord extends BaseActiveRecord
         $n = 0;
         $errors = [];
         foreach ($response['items'] as $item) {
-            if (isset($item['update']['error'])) {
-                $errors[] = $item['update'];
-            } elseif ($item['update']['ok']) {
+            if (isset($item['update']['status']) && $item['update']['status'] == 200) {
                 $n++;
+            } else {
+                $errors[] = $item['update'];
             }
         }
-        if (!empty($errors)) {
+        if (!empty($errors) || isset($response['errors']) && $response['errors']) {
             throw new Exception(__METHOD__ . ' failed updating records counters.', $errors);
         }
 
@@ -563,13 +578,15 @@ class ActiveRecord extends BaseActiveRecord
         $n = 0;
         $errors = [];
         foreach ($response['items'] as $item) {
-            if (isset($item['delete']['error'])) {
+            if (isset($item['delete']['status']) && $item['delete']['status'] == 200) {
+                if (isset($item['delete']['found']) && $item['delete']['found']) {
+                    $n++;
+                }
+            } else {
                 $errors[] = $item['delete'];
-            } elseif ($item['delete']['found'] && $item['delete']['ok']) {
-                $n++;
             }
         }
-        if (!empty($errors)) {
+        if (!empty($errors) || isset($response['errors']) && $response['errors']) {
             throw new Exception(__METHOD__ . ' failed deleting records.', $errors);
         }
 
diff --git a/extensions/elasticsearch/CHANGELOG.md b/extensions/elasticsearch/CHANGELOG.md
index 6b69719..3710c97 100644
--- a/extensions/elasticsearch/CHANGELOG.md
+++ b/extensions/elasticsearch/CHANGELOG.md
@@ -4,7 +4,9 @@ Yii Framework 2 elasticsearch extension Change Log
 2.0.0-rc under development
 --------------------------
 
-- no changes in this release.
+- Chg: asArray in ActiveQuery is now equal to using the normal Query. This means, that the output structure has changed and `with` is supported anymore. (cebe)
+- Chg: Deletion of a record is now also considered successfull if the record did not exist. (cebe)
+- Chg: Requirement changes: Yii now requires elasticsearch version 1.0 or higher (cebe)
 
 
 2.0.0-beta April 13, 2014
diff --git a/extensions/elasticsearch/Command.php b/extensions/elasticsearch/Command.php
index 560992b..f1313ad 100644
--- a/extensions/elasticsearch/Command.php
+++ b/extensions/elasticsearch/Command.php
@@ -315,7 +315,7 @@ class Command extends Component
     {
         $body = $mapping !== null ? (is_string($mapping) ? $mapping : Json::encode($mapping)) : null;
 
-        return $this->db->put([$index, $type, '_mapping'], $options, $body);
+        return $this->db->put([$index, '_mapping', $type], $options, $body);
     }
 
     /**
@@ -326,7 +326,7 @@ class Command extends Component
      */
     public function getMapping($index = '_all', $type = '_all')
     {
-        return $this->db->get([$index, $type, '_mapping']);
+        return $this->db->get([$index, '_mapping', $type]);
     }
 
     /**
@@ -337,7 +337,7 @@ class Command extends Component
      */
     public function deleteMapping($index, $type)
     {
-        return $this->db->delete([$index, $type]);
+        return $this->db->delete([$index, '_mapping', $type]);
     }
 
     /**
@@ -346,10 +346,11 @@ class Command extends Component
      * @return mixed
      * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html
      */
-    public function getFieldMapping($index, $type = '_all')
-    {
-        return $this->db->put([$index, $type, '_mapping']);
-    }
+//    public function getFieldMapping($index, $type = '_all')
+//    {
+//		// TODO implement
+//        return $this->db->put([$index, $type, '_mapping']);
+//    }
 
     /**
      * @param $options
diff --git a/extensions/elasticsearch/Connection.php b/extensions/elasticsearch/Connection.php
index 5d0737b..8a8124d 100644
--- a/extensions/elasticsearch/Connection.php
+++ b/extensions/elasticsearch/Connection.php
@@ -109,7 +109,7 @@ class Connection extends Component
             if (strncmp($host, 'inet[/', 6) == 0) {
                 $host = substr($host, 6, -1);
             }
-            $response = $this->httpRequest('GET', 'http://' . $host . '/_cluster/nodes');
+            $response = $this->httpRequest('GET', 'http://' . $host . '/_nodes');
             $this->nodes = $response['nodes'];
             if (empty($this->nodes)) {
                 throw new Exception('cluster autodetection did not find any active node.');
diff --git a/extensions/elasticsearch/Query.php b/extensions/elasticsearch/Query.php
index dc9996b..535e1c8 100644
--- a/extensions/elasticsearch/Query.php
+++ b/extensions/elasticsearch/Query.php
@@ -58,13 +58,52 @@ class Query extends Component implements QueryInterface
 
     /**
      * @var array the fields being retrieved from the documents. For example, `['id', 'name']`.
-     * If not set, it means retrieving all fields. An empty array will result in no fields being
-     * retrieved. This means that only the primaryKey of a record will be available in the result.
+     * If not set, this option will not be applied to the query and no fields will be returned.
+     * In this case the `_source` field will be returned by default which can be configured using [[source]].
+     * Setting this to an empty array will result in no fields being retrieved, which means that only the primaryKey
+     * of a record will be available in the result.
+     *
+     * For each field you may also add an array representing a [script field]. Example:
+     *
+     * ```php
+     * $query->fields = [
+     *     'id',
+     *     'name',
+     *     'value_times_two' => [
+     *         'script' => "doc['my_field_name'].value * 2",
+     *     ],
+     *     'value_times_factor' => [
+     *         'script' => "doc['my_field_name'].value * factor",
+     *         'params' => [
+     *             'factor' => 2.0
+     *         ],
+     *     ],
+     * ]
+     * ```
+     *
+     * > Note: Field values are [always returned as arrays] even if they only have one value.
+     *
+     * [always returned as arrays]: http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/_return_values.html#_return_values
+     * [script field]: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-script-fields.html
+     *
      * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-fields.html#search-request-fields
+     * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-script-fields.html
      * @see fields()
+     * @see source
      */
     public $fields;
     /**
+     * @var array this option controls how the `_source` field is returned from the documents. For example, `['id', 'name']`
+     * means that only the `id` and `name` field should be returned from `_source`.
+     * If not set, it means retrieving the full `_source` field unless [[fields]] are specified.
+     * Setting this option to `false` will disable return of the `_source` field, this means that only the primaryKey
+     * of a record will be available in the result.
+     * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-source-filtering.html
+     * @see source()
+     * @see fields
+     */
+    public $source;
+    /**
      * @var string|array The index to retrieve data from. This can be a string representing a single index
      * or a an array of multiple indexes. If this is not set, indexes are being queried.
      * @see from()
@@ -137,25 +176,20 @@ class Query extends Component implements QueryInterface
             return [];
         }
         $rows = $result['hits']['hits'];
-        if ($this->indexBy === null && $this->fields === null) {
+        if ($this->indexBy === null) {
             return $rows;
         }
         $models = [];
         foreach ($rows as $key => $row) {
-            if ($this->fields !== null) {
-                $row['_source'] = isset($row['fields']) ? $row['fields'] : [];
-                unset($row['fields']);
-            }
             if ($this->indexBy !== null) {
                 if (is_string($this->indexBy)) {
-                    $key = $row['_source'][$this->indexBy];
+                    $key = isset($row['fields'][$this->indexBy]) ? reset($row['fields'][$this->indexBy]) : $row['_source'][$this->indexBy];
                 } else {
                     $key = call_user_func($this->indexBy, $row);
                 }
             }
             $models[$key] = $row;
         }
-
         return $models;
     }
 
@@ -173,10 +207,6 @@ class Query extends Component implements QueryInterface
             return false;
         }
         $record = reset($result['hits']['hits']);
-        if ($this->fields !== null) {
-            $record['_source'] = isset($record['fields']) ? $record['fields'] : [];
-            unset($record['fields']);
-        }
 
         return $record;
     }
@@ -195,25 +225,18 @@ class Query extends Component implements QueryInterface
     public function search($db = null, $options = [])
     {
         $result = $this->createCommand($db)->search($options);
-        if (!empty($result['hits']['hits']) && ($this->indexBy === null || $this->fields === null)) {
+        if (!empty($result['hits']['hits']) && $this->indexBy !== null) {
             $rows = [];
             foreach ($result['hits']['hits'] as $key => $row) {
-                if ($this->fields !== null) {
-                    $row['_source'] = isset($row['fields']) ? $row['fields'] : [];
-                    unset($row['fields']);
-                }
-                if ($this->indexBy !== null) {
-                    if (is_string($this->indexBy)) {
-                        $key = $row['_source'][$this->indexBy];
-                    } else {
-                        $key = call_user_func($this->indexBy, $row);
-                    }
+                if (is_string($this->indexBy)) {
+                    $key = isset($row['fields'][$this->indexBy]) ? $row['fields'][$this->indexBy] : $row['_source'][$this->indexBy];
+                } else {
+                    $key = call_user_func($this->indexBy, $row);
                 }
                 $rows[$key] = $row;
             }
             $result['hits']['hits'] = $rows;
         }
-
         return $result;
     }
 
@@ -247,12 +270,17 @@ class Query extends Component implements QueryInterface
      */
     public function scalar($field, $db = null)
     {
-        $record = self::one($db); // TODO limit fields to the one required
-        if ($record !== false && isset($record['_source'][$field])) {
-            return $record['_source'][$field];
-        } else {
-            return null;
+        $record = self::one($db);
+        if ($record !== false) {
+            if ($field === '_id') {
+                return $record['_id'];
+            } elseif (isset($record['_source'][$field])) {
+                return $record['_source'][$field];
+            } elseif (isset($record['fields'][$field])) {
+                return count($record['fields'][$field]) == 1 ? reset($record['fields'][$field]) : $record['fields'][$field];
+            }
         }
+        return null;
     }
 
     /**
@@ -265,14 +293,14 @@ class Query extends Component implements QueryInterface
     public function column($field, $db = null)
     {
         $command = $this->createCommand($db);
-        $command->queryParts['fields'] = [$field];
+        $command->queryParts['_source'] = [$field];
         $result = $command->search();
         if (empty($result['hits']['hits'])) {
             return [];
         }
         $column = [];
         foreach ($result['hits']['hits'] as $row) {
-            $column[] = isset($row['fields'][$field]) ? $row['fields'][$field] : null;
+            $column[] = isset($row['_source'][$field]) ? $row['_source'][$field] : null;
         }
         return $column;
     }
@@ -498,6 +526,22 @@ class Query extends Component implements QueryInterface
     }
 
     /**
+     * Sets the source filtering, specifying how the `_source` field of the document should be returned.
+     * @param array $source the source patterns to be selected.
+     * @return static the query object itself
+     * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-source-filtering.html
+     */
+    public function source($source)
+    {
+        if (is_array($source) || $source === null) {
+            $this->source = $source;
+        } else {
+            $this->source = func_get_args();
+        }
+        return $this;
+    }
+
+    /**
      * Sets the search timeout.
      * @param integer $timeout A search timeout, bounding the search request to be executed within the specified time value
      * and bail with the hits accumulated up to that point when expired. Defaults to no timeout.
diff --git a/extensions/elasticsearch/QueryBuilder.php b/extensions/elasticsearch/QueryBuilder.php
index 7d0e770..951e6f6 100644
--- a/extensions/elasticsearch/QueryBuilder.php
+++ b/extensions/elasticsearch/QueryBuilder.php
@@ -45,8 +45,27 @@ class QueryBuilder extends \yii\base\Object
     {
         $parts = [];
 
-        if ($query->fields !== null) {
-            $parts['fields'] = (array) $query->fields;
+        if ($query->fields === []) {
+            $parts['fields'] = [];
+        } elseif ($query->fields !== null) {
+            $fields = [];
+            $scriptFields = [];
+            foreach($query->fields as $key => $field) {
+                if (is_int($key)) {
+                    $fields[] = $field;
+                } else {
+                    $scriptFields[$key] = $field;
+                }
+            }
+            if (!empty($fields)) {
+                $parts['fields'] = $fields;
+            }
+            if (!empty($scriptFields)) {
+                $parts['script_fields'] = $scriptFields;
+            }
+        }
+        if ($query->source !== null) {
+            $parts['_source'] = $query->source;
         }
         if ($query->limit !== null && $query->limit >= 0) {
             $parts['size'] = $query->limit;
diff --git a/extensions/elasticsearch/README.md b/extensions/elasticsearch/README.md
index e952f0a..0875e8e 100644
--- a/extensions/elasticsearch/README.md
+++ b/extensions/elasticsearch/README.md
@@ -22,6 +22,10 @@ return [
 ];
 ```
 
+Requirements
+------------
+
+elasticsearch version 1.0 or higher is required.
 
 Installation
 ------------
diff --git a/extensions/gii/views/default/index.php b/extensions/gii/views/default/index.php
index 0ba6529..05ce312 100644
--- a/extensions/gii/views/default/index.php
+++ b/extensions/gii/views/default/index.php
@@ -11,7 +11,7 @@ $this->title = 'Welcome to Gii';
 ?>
 <div class="default-index">
     <div class="page-header">
-        <h1>Welcome to Gii <small>a magic tool that can write code for you</small></h1>
+        <h1>Welcome to Gii <small>a magical tool that can write code for you</small></h1>
     </div>
 
     <p class="lead">Start the fun with the following code generators:</p>
diff --git a/extensions/mongodb/CHANGELOG.md b/extensions/mongodb/CHANGELOG.md
index a3292d7..0d1b697 100644
--- a/extensions/mongodb/CHANGELOG.md
+++ b/extensions/mongodb/CHANGELOG.md
@@ -4,7 +4,7 @@ Yii Framework 2 mongodb extension Change Log
 2.0.0-rc under development
 --------------------------
 
-- no changes in this release.
+- Bug #3385: Fixed "The 'connected' property is deprecated" (samdark)
 
 
 2.0.0-beta April 13, 2014
diff --git a/extensions/mongodb/Connection.php b/extensions/mongodb/Connection.php
index fab3e88..50ff815 100644
--- a/extensions/mongodb/Connection.php
+++ b/extensions/mongodb/Connection.php
@@ -219,7 +219,7 @@ class Connection extends Component
      */
     public function getIsActive()
     {
-        return is_object($this->mongoClient) && $this->mongoClient->connected;
+        return is_object($this->mongoClient) && $this->mongoClient->getConnections() != [];
     }
 
     /**
diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md
index ba03abc..034446a 100644
--- a/framework/CHANGELOG.md
+++ b/framework/CHANGELOG.md
@@ -25,6 +25,7 @@ Yii Framework 2 Change Log
 - Bug #3311: Fixed the bug that `yii\di\Container::has()` did not return correct value (mgrechanik, qiangxue)
 - Bug #3327: Fixed "Unable to find debug data" when logging objects with circular references (jarekkozak, samdark)
 - Bug #3368: Fix for comparing numeric attributes in JavaScript (technixp)
+- Bug: Fixed inconsistent return of `\yii\console\Application::runAction()` (samdark)
 - Enh #2264: `CookieCollection::has()` will return false for expired or removed cookies (qiangxue)
 - Enh #2435: `yii\db\IntegrityException` is now thrown on database integrity errors instead of general `yii\db\Exception` (samdark)
 - Enh #2837: Error page now shows arguments in stack trace method calls (samdark)
@@ -45,9 +46,12 @@ Yii Framework 2 Change Log
 - Enh: Supported adding a new response formatter without the need to reconfigure existing formatters (qiangxue)
 - Enh: Added `yii\web\UrlManager::addRules()` to simplify adding new URL rules (qiangxue)
 - Enh: Added support to insert an event handler at the beginning of class-level event handler queue (qiangxue)
+- Enh: Added `yii\console\Controller::EXIT_CODE_NORMAL` and `yii\console\Controller::EXIT_CODE_ERROR` constants (samdark)
+- Enh: `yii\console\MigrateController` now returns `yii\console\Controller::EXIT_CODE_ERROR` in case of failed migration (samdark)
 - Chg #2913: RBAC `DbManager` is now initialized via migration (samdark)
 - Chg #3036: Upgraded Twitter Bootstrap to 3.1.x (qiangxue)
 - Chg #3175: InvalidCallException, InvalidParamException, UnknownMethodException are now extended from SPL BadMethodCallException (samdark)
+- Chg #3383: Added `$type` parameter to `IdentityInterface::findIdentityByAccessToken()` (qiangxue)
 - Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue)
 - Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue)
 - Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe)
diff --git a/framework/UPGRADE.md b/framework/UPGRADE.md
index be0e4a5..ffbade4 100644
--- a/framework/UPGRADE.md
+++ b/framework/UPGRADE.md
@@ -21,3 +21,11 @@ Upgrade from Yii 2.0 Beta
 
 * If you override `yii\grid\DataColumn::getDataCellValue()` with visibility `protected` you have
   to change visibility to `public` as visibility of the base method has changed.
+
+* If you have classes implementing `yii\web\IdentityInterface` (very common), you should modify
+  the signature of `findIdentityByAccessToken()` as
+  `public static function findIdentityByAccessToken($token, $type = null)`. The new `$type` parameter
+  will contain the type information about the access token. For example, if you use
+  `yii\filters\auth\HttpBearerAuth` authentication method, the value of this parameter will be
+  `yii\filters\auth\HttpBearerAuth`. This allows you to differentiate access tokens taken by
+  different authentication methods.
diff --git a/framework/base/Object.php b/framework/base/Object.php
index a5b9d3f..73e4240 100644
--- a/framework/base/Object.php
+++ b/framework/base/Object.php
@@ -77,6 +77,7 @@ use Yii;
 class Object
 {
     /**
+     * Returns the fully qualified name of this class.
      * @return string the fully qualified name of this class.
      */
     public static function className()
diff --git a/framework/base/Widget.php b/framework/base/Widget.php
index ea7358d..95946ba 100644
--- a/framework/base/Widget.php
+++ b/framework/base/Widget.php
@@ -54,7 +54,7 @@ class Widget extends Component implements ViewContextInterface
         $config['class'] = get_called_class();
         /** @var Widget $widget */
         $widget = Yii::createObject($config);
-        self::$stack[] = $widget;
+        static::$stack[] = $widget;
 
         return $widget;
     }
@@ -67,8 +67,8 @@ class Widget extends Component implements ViewContextInterface
      */
     public static function end()
     {
-        if (!empty(self::$stack)) {
-            $widget = array_pop(self::$stack);
+        if (!empty(static::$stack)) {
+            $widget = array_pop(static::$stack);
             if (get_class($widget) === get_called_class()) {
                 echo $widget->run();
                 return $widget;
@@ -108,7 +108,7 @@ class Widget extends Component implements ViewContextInterface
     public function getId($autoGenerate = true)
     {
         if ($autoGenerate && $this->_id === null) {
-            $this->_id = self::$autoIdPrefix . self::$counter++;
+            $this->_id = static::$autoIdPrefix . static::$counter++;
         }
 
         return $this->_id;
diff --git a/framework/console/Application.php b/framework/console/Application.php
index b373e7e..913e3af 100644
--- a/framework/console/Application.php
+++ b/framework/console/Application.php
@@ -138,7 +138,7 @@ class Application extends \yii\base\Application
             return $result;
         } else {
             $response = $this->getResponse();
-            $response->exitStatus = (int) $result;
+            $response->exitStatus = $result;
 
             return $response;
         }
@@ -157,7 +157,7 @@ class Application extends \yii\base\Application
     public function runAction($route, $params = [])
     {
         try {
-            return parent::runAction($route, $params);
+            return (int)parent::runAction($route, $params);
         } catch (InvalidRouteException $e) {
             throw new Exception(Yii::t('yii', 'Unknown command "{command}".', ['command' => $route]), 0, $e);
         }
diff --git a/framework/console/Controller.php b/framework/console/Controller.php
index a927692..362e39c 100644
--- a/framework/console/Controller.php
+++ b/framework/console/Controller.php
@@ -29,6 +29,9 @@ use yii\helpers\Console;
  */
 class Controller extends \yii\base\Controller
 {
+    const EXIT_CODE_NORMAL = 0;
+    const EXIT_CODE_ERROR = 1;
+
     /**
      * @var boolean whether to run the command interactively.
      */
diff --git a/framework/console/controllers/AssetController.php b/framework/console/controllers/AssetController.php
index c23761b..b7e1356 100644
--- a/framework/console/controllers/AssetController.php
+++ b/framework/console/controllers/AssetController.php
@@ -611,7 +611,7 @@ return [
 EOD;
         if (file_exists($configFile)) {
             if (!$this->confirm("File '{$configFile}' already exists. Do you wish to overwrite it?")) {
-                return;
+                return self::EXIT_CODE_NORMAL;
             }
         }
         if (!file_put_contents($configFile, $template)) {
diff --git a/framework/console/controllers/FixtureController.php b/framework/console/controllers/FixtureController.php
index d798268..8978298 100644
--- a/framework/console/controllers/FixtureController.php
+++ b/framework/console/controllers/FixtureController.php
@@ -96,7 +96,7 @@ class FixtureController extends Controller
         }
 
         if (!$this->confirmLoad($foundFixtures, $except)) {
-            return;
+            return self::EXIT_CODE_NORMAL;
         }
 
         $filtered = array_diff($foundFixtures, $except);
@@ -140,7 +140,7 @@ class FixtureController extends Controller
         }
 
         if (!$this->confirmUnload($foundFixtures, $except)) {
-            return;
+            return self::EXIT_CODE_NORMAL;
         }
 
         $filtered = array_diff($foundFixtures, $except);
diff --git a/framework/console/controllers/MessageController.php b/framework/console/controllers/MessageController.php
index ec32561..e3ba05a 100644
--- a/framework/console/controllers/MessageController.php
+++ b/framework/console/controllers/MessageController.php
@@ -54,7 +54,7 @@ class MessageController extends Controller
         $filePath = Yii::getAlias($filePath);
         if (file_exists($filePath)) {
             if (!$this->confirm("File '{$filePath}' already exists. Do you wish to overwrite it?")) {
-                return;
+                return self::EXIT_CODE_NORMAL;
             }
         }
         copy(Yii::getAlias('@yii/views/messageConfig.php'), $filePath);
@@ -298,7 +298,7 @@ class MessageController extends Controller
             if (array_keys($translated) == $messages) {
                 echo "nothing new...skipped.\n";
 
-                return;
+                return self::EXIT_CODE_NORMAL;
             }
             $merged = [];
             $untranslated = [];
diff --git a/framework/console/controllers/MigrateController.php b/framework/console/controllers/MigrateController.php
index 8ed9994..77fbbc9 100644
--- a/framework/console/controllers/MigrateController.php
+++ b/framework/console/controllers/MigrateController.php
@@ -81,10 +81,6 @@ class MigrateController extends Controller
      */
     public $templateFile = '@yii/views/migration.php';
     /**
-     * @var boolean whether to execute the migration in an interactive mode.
-     */
-    public $interactive = true;
-    /**
      * @var Connection|string the DB connection object or the application
      * component ID of the DB connection.
      */
@@ -148,6 +144,8 @@ class MigrateController extends Controller
      *
      * @param integer $limit the number of new migrations to be applied. If 0, it means
      * applying all available new migrations.
+     *
+     * @return integer the status of the action execution. 0 means normal, other values mean abnormal.
      */
     public function actionUp($limit = 0)
     {
@@ -155,7 +153,7 @@ class MigrateController extends Controller
         if (empty($migrations)) {
             echo "No new migration found. Your system is up-to-date.\n";
 
-            return;
+            return self::EXIT_CODE_NORMAL;
         }
 
         $total = count($migrations);
@@ -181,7 +179,7 @@ class MigrateController extends Controller
                 if (!$this->migrateUp($migration)) {
                     echo "\nMigration failed. The rest of the migrations are canceled.\n";
 
-                    return;
+                    return self::EXIT_CODE_ERROR;
                 }
             }
             echo "\nMigrated up successfully.\n";
@@ -200,6 +198,8 @@ class MigrateController extends Controller
      * @param integer $limit the number of migrations to be reverted. Defaults to 1,
      * meaning the last applied migration will be reverted.
      * @throws Exception if the number of the steps specified is less than 1.
+     *
+     * @return integer the status of the action execution. 0 means normal, other values mean abnormal.
      */
     public function actionDown($limit = 1)
     {
@@ -212,7 +212,7 @@ class MigrateController extends Controller
         if (empty($migrations)) {
             echo "No migration has been done before.\n";
 
-            return;
+            return self::EXIT_CODE_NORMAL;
         }
         $migrations = array_keys($migrations);
 
@@ -228,7 +228,7 @@ class MigrateController extends Controller
                 if (!$this->migrateDown($migration)) {
                     echo "\nMigration failed. The rest of the migrations are canceled.\n";
 
-                    return;
+                    return self::EXIT_CODE_ERROR;
                 }
             }
             echo "\nMigrated down successfully.\n";
@@ -249,6 +249,8 @@ class MigrateController extends Controller
      * @param integer $limit the number of migrations to be redone. Defaults to 1,
      * meaning the last applied migration will be redone.
      * @throws Exception if the number of the steps specified is less than 1.
+     *
+     * @return integer the status of the action execution. 0 means normal, other values mean abnormal.
      */
     public function actionRedo($limit = 1)
     {
@@ -261,7 +263,7 @@ class MigrateController extends Controller
         if (empty($migrations)) {
             echo "No migration has been done before.\n";
 
-            return;
+            return self::EXIT_CODE_NORMAL;
         }
         $migrations = array_keys($migrations);
 
@@ -277,14 +279,14 @@ class MigrateController extends Controller
                 if (!$this->migrateDown($migration)) {
                     echo "\nMigration failed. The rest of the migrations are canceled.\n";
 
-                    return;
+                    return self::EXIT_CODE_ERROR;
                 }
             }
             foreach (array_reverse($migrations) as $migration) {
                 if (!$this->migrateUp($migration)) {
                     echo "\nMigration failed. The rest of the migrations migrations are canceled.\n";
 
-                    return;
+                    return self::EXIT_CODE_ERROR;
                 }
             }
             echo "\nMigration redone successfully.\n";
@@ -365,7 +367,7 @@ class MigrateController extends Controller
                     echo "The migration history is set at $originalVersion.\nNo actual migration was performed.\n";
                 }
 
-                return;
+                return self::EXIT_CODE_NORMAL;
             }
         }
 
@@ -387,7 +389,7 @@ class MigrateController extends Controller
                     }
                 }
 
-                return;
+                return self::EXIT_CODE_NORMAL;
             }
         }
 
@@ -602,7 +604,7 @@ class MigrateController extends Controller
             if (strpos($migration, $version . '_') === 0) {
                 $this->actionUp($i + 1);
 
-                return;
+                return self::EXIT_CODE_NORMAL;
             }
         }
 
@@ -616,7 +618,7 @@ class MigrateController extends Controller
                     $this->actionDown($i);
                 }
 
-                return;
+                return self::EXIT_CODE_NORMAL;
             }
         }
 
diff --git a/framework/filters/auth/HttpBasicAuth.php b/framework/filters/auth/HttpBasicAuth.php
index 565112c..594faed 100644
--- a/framework/filters/auth/HttpBasicAuth.php
+++ b/framework/filters/auth/HttpBasicAuth.php
@@ -77,7 +77,7 @@ class HttpBasicAuth extends AuthMethod
                 return $identity;
             }
         } elseif ($username !== null) {
-            $identity = $user->loginByAccessToken($username);
+            $identity = $user->loginByAccessToken($username, get_class($this));
             if ($identity === null) {
                 $this->handleFailure($response);
             }
diff --git a/framework/filters/auth/HttpBearerAuth.php b/framework/filters/auth/HttpBearerAuth.php
index d1d56a2..f21fcb3 100644
--- a/framework/filters/auth/HttpBearerAuth.php
+++ b/framework/filters/auth/HttpBearerAuth.php
@@ -43,7 +43,7 @@ class HttpBearerAuth extends AuthMethod
     {
         $authHeader = $request->getHeaders()->get('Authorization');
         if ($authHeader !== null && preg_match("/^Bearer\\s+(.*?)$/", $authHeader, $matches)) {
-            $identity = $user->loginByAccessToken($matches[1]);
+            $identity = $user->loginByAccessToken($matches[1], get_class($this));
             if ($identity === null) {
                 $this->handleFailure($response);
             }
diff --git a/framework/filters/auth/QueryParamAuth.php b/framework/filters/auth/QueryParamAuth.php
index 9c618d3..4b143b0 100644
--- a/framework/filters/auth/QueryParamAuth.php
+++ b/framework/filters/auth/QueryParamAuth.php
@@ -30,7 +30,7 @@ class QueryParamAuth extends AuthMethod
     {
         $accessToken = $request->get($this->tokenParam);
         if (is_string($accessToken)) {
-            $identity = $user->loginByAccessToken($accessToken);
+            $identity = $user->loginByAccessToken($accessToken, get_class($this));
             if ($identity !== null) {
                 return $identity;
             }
diff --git a/framework/i18n/GettextMessageSource.php b/framework/i18n/GettextMessageSource.php
index 306da15..4ddd2ba 100644
--- a/framework/i18n/GettextMessageSource.php
+++ b/framework/i18n/GettextMessageSource.php
@@ -98,9 +98,9 @@ class GettextMessageSource extends MessageSource
     {
         $messageFile = Yii::getAlias($this->basePath) . '/' . $language . '/' . $this->catalog;
         if ($this->useMoFile) {
-            $messageFile .= static::MO_FILE_EXT;
+            $messageFile .= self::MO_FILE_EXT;
         } else {
-            $messageFile .= static::PO_FILE_EXT;
+            $messageFile .= self::PO_FILE_EXT;
         }
 
         return $messageFile;
diff --git a/framework/rbac/DbManager.php b/framework/rbac/DbManager.php
index c2d31df..2e34a93 100644
--- a/framework/rbac/DbManager.php
+++ b/framework/rbac/DbManager.php
@@ -21,7 +21,7 @@ use yii\di\Instance;
  * The database connection is specified by [[db]]. The database schema could be initialized by applying migration:
  *
  * ```
- *  yii migrate --migrationPath=/vendor/yiisoft/yii2/rbac/migrations/
+ * yii migrate --migrationPath=@yii/rbac/migrations/
  * ```
  *
  * You may change the names of the three tables used to store the authorization data by setting [[itemTable]],
diff --git a/framework/rbac/migrations/m140506_102106_rbac_init.php b/framework/rbac/migrations/m140506_102106_rbac_init.php
index a05d94d..28af9ac 100644
--- a/framework/rbac/migrations/m140506_102106_rbac_init.php
+++ b/framework/rbac/migrations/m140506_102106_rbac_init.php
@@ -1,25 +1,42 @@
 <?php
 
+use yii\base\InvalidConfigException;
 use yii\db\Schema;
+use yii\rbac\DbManager;
 
 class m140506_102106_rbac_init extends \yii\db\Migration
 {
+    /**
+     * @throws yii\base\InvalidConfigException
+     * @return DbManager
+     */
+    protected function getAuthManager()
+    {
+        $authManager = Yii::$app->getAuthManager();
+        if (!$authManager instanceof DbManager) {
+            throw new InvalidConfigException('You should configure "authManager" component to use database before executing this migration.');
+        }
+        return $authManager;
+    }
+
     public function up()
     {
+        $authManager = $this->getAuthManager();
+
         $tableOptions = null;
         if ($this->db->driverName === 'mysql') {
             $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB';
         }
 
-        $this->createTable('{{%auth_rule}}', [
+        $this->createTable($authManager->ruleTable, [
             'name' => Schema::TYPE_STRING . '(64) NOT NULL',
             'data' => Schema::TYPE_TEXT,
             'created_at' => Schema::TYPE_INTEGER,
             'updated_at' => Schema::TYPE_INTEGER,
+            'PRIMARY KEY (name)',
         ], $tableOptions);
-        $this->addPrimaryKey('pk-auth_rule', '{{%auth_rule}}', 'name');
 
-        $this->createTable('{{%auth_item}}', [
+        $this->createTable($authManager->itemTable, [
             'name' => Schema::TYPE_STRING . '(64) NOT NULL',
             'type' => Schema::TYPE_INTEGER . ' NOT NULL',
             'description' => Schema::TYPE_TEXT,
@@ -27,33 +44,35 @@ class m140506_102106_rbac_init extends \yii\db\Migration
             'data' => Schema::TYPE_TEXT,
             'created_at' => Schema::TYPE_INTEGER,
             'updated_at' => Schema::TYPE_INTEGER,
+            'PRIMARY KEY (name)',
+            'FOREIGN KEY (rule_name) REFERENCES ' . $authManager->ruleTable . ' (name) ON DELETE SET NULL ON UPDATE CASCADE',
         ], $tableOptions);
-        $this->addPrimaryKey('pk-auth_item', '{{%auth_item}}', 'name');
-        $this->addForeignKey('fk-auth_item-rule_name', '{{%auth_item}}', 'rule_name', '{{%auth_rule}}', 'name', 'SET NULL', 'CASCADE');
-        $this->createIndex('idx-auth_item-type', '{{%auth_item}}', 'type');
+        $this->createIndex('idx-auth_item-type', $authManager->itemTable, 'type');
 
-        $this->createTable('{{%auth_item_child}}', [
+        $this->createTable($authManager->itemChildTable, [
             'parent' => Schema::TYPE_STRING . '(64) NOT NULL',
             'child' => Schema::TYPE_STRING . '(64) NOT NULL',
+            'PRIMARY KEY (parent, child)',
+            'FOREIGN KEY (parent) REFERENCES ' . $authManager->itemTable . ' (name) ON DELETE CASCADE ON UPDATE CASCADE',
+            'FOREIGN KEY (child) REFERENCES ' . $authManager->itemTable . ' (name) ON DELETE CASCADE ON UPDATE CASCADE',
         ], $tableOptions);
-        $this->addPrimaryKey('pk-auth_item_child', '{{%auth_item_child}}', ['parent', 'child']);
-        $this->addForeignKey('fk-auth_item_child-parent', '{{%auth_item_child}}', 'parent', '{{%auth_item}}', 'name', 'CASCADE', 'CASCADE');
-        $this->addForeignKey('fk-auth_item_child-child', '{{%auth_item_child}}', 'child', '{{%auth_item}}', 'name', 'CASCADE', 'CASCADE');
 
-        $this->createTable('{{%auth_assignment}}', [
+        $this->createTable($authManager->assignmentTable, [
             'item_name' => Schema::TYPE_STRING . '(64) NOT NULL',
             'user_id' => Schema::TYPE_STRING . '(64) NOT NULL',
             'created_at' => Schema::TYPE_INTEGER,
+            'PRIMARY KEY (item_name, user_id)',
+            'FOREIGN KEY (item_name) REFERENCES ' . $authManager->itemTable . ' (name) ON DELETE CASCADE ON UPDATE CASCADE',
         ], $tableOptions);
-        $this->addPrimaryKey('pk-auth_assignment', '{{%auth_assignment}}', ['item_name', 'user_id']);
-        $this->addForeignKey('fk-auth_assignment-item_name', '{{%auth_assignment}}', 'item_name', '{{%auth_item}}', 'name', 'CASCADE', 'CASCADE');
     }
 
     public function down()
     {
-        $this->dropTable('{{%auth_assignment}}');
-        $this->dropTable('{{%auth_item_child}}');
-        $this->dropTable('{{%auth_item}}');
-        $this->dropTable('{{%auth_rule}}');
+        $authManager = $this->getAuthManager();
+
+        $this->dropTable($authManager->assignmentTable);
+        $this->dropTable($authManager->itemChildTable);
+        $this->dropTable($authManager->itemTable);
+        $this->dropTable($authManager->ruleTable);
     }
 }
diff --git a/framework/web/IdentityInterface.php b/framework/web/IdentityInterface.php
index 423361e..9ab1125 100644
--- a/framework/web/IdentityInterface.php
+++ b/framework/web/IdentityInterface.php
@@ -21,7 +21,7 @@ namespace yii\web;
  *         return static::findOne($id);
  *     }
  *
- *     public static function findIdentityByAccessToken($token)
+ *     public static function findIdentityByAccessToken($token, $type = null)
  *     {
  *         return static::findOne(['access_token' => $token]);
  *     }
@@ -59,11 +59,13 @@ interface IdentityInterface
     /**
      * Finds an identity by the given secrete token.
      * @param string $token the secrete token
+     * @param mixed $type the type of the token. The value of this parameter depends on the implementation.
+     * For example, [[\yii\filters\auth\HttpBearerAuth]] will set this parameter to be `yii\filters\auth\HttpBearerAuth`.
      * @return IdentityInterface the identity object that matches the given token.
      * Null should be returned if such an identity cannot be found
      * or the identity is not in an active state (disabled, deleted, etc.)
      */
-    public static function findIdentityByAccessToken($token);
+    public static function findIdentityByAccessToken($token, $type = null);
     /**
      * Returns an ID that can uniquely identify a user identity.
      * @return string|integer an ID that uniquely identifies a user identity.
diff --git a/framework/web/User.php b/framework/web/User.php
index 2e375a1..78d25b3 100644
--- a/framework/web/User.php
+++ b/framework/web/User.php
@@ -216,14 +216,16 @@ class User extends Component
      * Note that unlike [[login()]], this method will NOT start a session to remember the user authentication status.
      * Also if the access token is invalid, the user will remain as a guest.
      * @param string $token the access token
+     * @param mixed $type the type of the token. The value of this parameter depends on the implementation.
+     * For example, [[\yii\filters\auth\HttpBearerAuth]] will set this parameter to be `yii\filters\auth\HttpBearerAuth`.
      * @return IdentityInterface the identity associated with the given access token. Null is returned if
      * the access token is invalid.
      */
-    public function loginByAccessToken($token)
+    public function loginByAccessToken($token, $type = null)
     {
         /** @var IdentityInterface $class */
         $class = $this->identityClass;
-        $identity = $class::findIdentityByAccessToken($token);
+        $identity = $class::findIdentityByAccessToken($token, $type);
         $this->setIdentity($identity);
 
         return $identity;
diff --git a/tests/unit/TestCase.php b/tests/unit/TestCase.php
index 37b4313..4d9b7aa 100644
--- a/tests/unit/TestCase.php
+++ b/tests/unit/TestCase.php
@@ -27,7 +27,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
      * @param  mixed  $default default value to use when param is not set.
      * @return mixed  the value of the configuration param
      */
-    public function getParam($name, $default = null)
+    public static function getParam($name, $default = null)
     {
         if (static::$params === null) {
             static::$params = require(__DIR__ . '/data/config.php');
diff --git a/tests/unit/data/ar/elasticsearch/OrderItem.php b/tests/unit/data/ar/elasticsearch/OrderItem.php
index 1e1b6e6..4541559 100644
--- a/tests/unit/data/ar/elasticsearch/OrderItem.php
+++ b/tests/unit/data/ar/elasticsearch/OrderItem.php
@@ -14,6 +14,8 @@ use yii\elasticsearch\Command;
  */
 class OrderItem extends ActiveRecord
 {
+    public $total;
+
     public function attributes()
     {
         return ['order_id', 'item_id', 'quantity', 'subtotal'];
diff --git a/tests/unit/extensions/elasticsearch/ActiveRecordTest.php b/tests/unit/extensions/elasticsearch/ActiveRecordTest.php
index bb95219..125df42 100644
--- a/tests/unit/extensions/elasticsearch/ActiveRecordTest.php
+++ b/tests/unit/extensions/elasticsearch/ActiveRecordTest.php
@@ -151,8 +151,8 @@ class ActiveRecordTest extends ElasticSearchTestCase
             'name' => 'user2',
             'address' => 'address2',
             'status' => 1,
-            '_score' => 1.0
-        ], $customer);
+//            '_score' => 1.0
+        ], $customer['_source']);
     }
 
     public function testSearch()
@@ -174,21 +174,21 @@ class ActiveRecordTest extends ElasticSearchTestCase
         $this->assertEquals(3, $result['total']);
         $customers = $result['hits'];
         $this->assertEquals(3, count($customers));
-        $this->assertArrayHasKey('id', $customers[0]);
-        $this->assertArrayHasKey('name', $customers[0]);
-        $this->assertArrayHasKey('email', $customers[0]);
-        $this->assertArrayHasKey('address', $customers[0]);
-        $this->assertArrayHasKey('status', $customers[0]);
-        $this->assertArrayHasKey('id', $customers[1]);
-        $this->assertArrayHasKey('name', $customers[1]);
-        $this->assertArrayHasKey('email', $customers[1]);
-        $this->assertArrayHasKey('address', $customers[1]);
-        $this->assertArrayHasKey('status', $customers[1]);
-        $this->assertArrayHasKey('id', $customers[2]);
-        $this->assertArrayHasKey('name', $customers[2]);
-        $this->assertArrayHasKey('email', $customers[2]);
-        $this->assertArrayHasKey('address', $customers[2]);
-        $this->assertArrayHasKey('status', $customers[2]);
+        $this->assertArrayHasKey('id', $customers[0]['_source']);
+        $this->assertArrayHasKey('name', $customers[0]['_source']);
+        $this->assertArrayHasKey('email', $customers[0]['_source']);
+        $this->assertArrayHasKey('address', $customers[0]['_source']);
+        $this->assertArrayHasKey('status', $customers[0]['_source']);
+        $this->assertArrayHasKey('id', $customers[1]['_source']);
+        $this->assertArrayHasKey('name', $customers[1]['_source']);
+        $this->assertArrayHasKey('email', $customers[1]['_source']);
+        $this->assertArrayHasKey('address', $customers[1]['_source']);
+        $this->assertArrayHasKey('status', $customers[1]['_source']);
+        $this->assertArrayHasKey('id', $customers[2]['_source']);
+        $this->assertArrayHasKey('name', $customers[2]['_source']);
+        $this->assertArrayHasKey('email', $customers[2]['_source']);
+        $this->assertArrayHasKey('address', $customers[2]['_source']);
+        $this->assertArrayHasKey('status', $customers[2]['_source']);
 
         // TODO test asArray() + fields() + indexBy()
 
@@ -387,35 +387,67 @@ class ActiveRecordTest extends ElasticSearchTestCase
         $this->assertEquals(2, count($customers));
     }
 
+    public function testScriptFields()
+    {
+        $orderItems = OrderItem::find()->fields(['quantity', 'subtotal', 'total' => ['script' => "doc['quantity'].value * doc['subtotal'].value"]])->all();
+        foreach($orderItems as $item) {
+            $this->assertEquals($item->subtotal * $item->quantity, $item->total);
+        }
+    }
+
     public function testFindAsArrayFields()
     {
         /** @var TestCase|ActiveRecordTestTrait $this */
         // indexBy + asArray
         $customers = Customer::find()->asArray()->fields(['id', 'name'])->all();
         $this->assertEquals(3, count($customers));
-        $this->assertArrayHasKey('id', $customers[0]);
-        $this->assertArrayHasKey('name', $customers[0]);
-        $this->assertArrayNotHasKey('email', $customers[0]);
-        $this->assertArrayNotHasKey('address', $customers[0]);
-        $this->assertArrayNotHasKey('status', $customers[0]);
-        $this->assertArrayHasKey('id', $customers[1]);
-        $this->assertArrayHasKey('name', $customers[1]);
-        $this->assertArrayNotHasKey('email', $customers[1]);
-        $this->assertArrayNotHasKey('address', $customers[1]);
-        $this->assertArrayNotHasKey('status', $customers[1]);
-        $this->assertArrayHasKey('id', $customers[2]);
-        $this->assertArrayHasKey('name', $customers[2]);
-        $this->assertArrayNotHasKey('email', $customers[2]);
-        $this->assertArrayNotHasKey('address', $customers[2]);
-        $this->assertArrayNotHasKey('status', $customers[2]);
+        $this->assertArrayHasKey('id', $customers[0]['fields']);
+        $this->assertArrayHasKey('name', $customers[0]['fields']);
+        $this->assertArrayNotHasKey('email', $customers[0]['fields']);
+        $this->assertArrayNotHasKey('address', $customers[0]['fields']);
+        $this->assertArrayNotHasKey('status', $customers[0]['fields']);
+        $this->assertArrayHasKey('id', $customers[1]['fields']);
+        $this->assertArrayHasKey('name', $customers[1]['fields']);
+        $this->assertArrayNotHasKey('email', $customers[1]['fields']);
+        $this->assertArrayNotHasKey('address', $customers[1]['fields']);
+        $this->assertArrayNotHasKey('status', $customers[1]['fields']);
+        $this->assertArrayHasKey('id', $customers[2]['fields']);
+        $this->assertArrayHasKey('name', $customers[2]['fields']);
+        $this->assertArrayNotHasKey('email', $customers[2]['fields']);
+        $this->assertArrayNotHasKey('address', $customers[2]['fields']);
+        $this->assertArrayNotHasKey('status', $customers[2]['fields']);
     }
 
-    public function testFindIndexByFields()
+    public function testFindAsArraySourceFilter()
+    {
+        /** @var TestCase|ActiveRecordTestTrait $this */
+        // indexBy + asArray
+        $customers = Customer::find()->asArray()->source(['id', 'name'])->all();
+        $this->assertEquals(3, count($customers));
+        $this->assertArrayHasKey('id', $customers[0]['_source']);
+        $this->assertArrayHasKey('name', $customers[0]['_source']);
+        $this->assertArrayNotHasKey('email', $customers[0]['_source']);
+        $this->assertArrayNotHasKey('address', $customers[0]['_source']);
+        $this->assertArrayNotHasKey('status', $customers[0]['_source']);
+        $this->assertArrayHasKey('id', $customers[1]['_source']);
+        $this->assertArrayHasKey('name', $customers[1]['_source']);
+        $this->assertArrayNotHasKey('email', $customers[1]['_source']);
+        $this->assertArrayNotHasKey('address', $customers[1]['_source']);
+        $this->assertArrayNotHasKey('status', $customers[1]['_source']);
+        $this->assertArrayHasKey('id', $customers[2]['_source']);
+        $this->assertArrayHasKey('name', $customers[2]['_source']);
+        $this->assertArrayNotHasKey('email', $customers[2]['_source']);
+        $this->assertArrayNotHasKey('address', $customers[2]['_source']);
+        $this->assertArrayNotHasKey('status', $customers[2]['_source']);
+    }
+
+
+    public function testFindIndexBySource()
     {
         $customerClass = $this->getCustomerClass();
         /** @var TestCase|ActiveRecordTestTrait $this */
         // indexBy + asArray
-        $customers = Customer::find()->indexBy('name')->fields('id', 'name')->all();
+        $customers = Customer::find()->indexBy('name')->source('id', 'name')->all();
         $this->assertEquals(3, count($customers));
         $this->assertTrue($customers['user1'] instanceof $customerClass);
         $this->assertTrue($customers['user2'] instanceof $customerClass);
@@ -467,42 +499,89 @@ class ActiveRecordTest extends ElasticSearchTestCase
         // indexBy + asArray
         $customers = Customer::find()->indexBy('name')->asArray()->fields('id', 'name')->all();
         $this->assertEquals(3, count($customers));
-        $this->assertArrayHasKey('id', $customers['user1']);
-        $this->assertArrayHasKey('name', $customers['user1']);
-        $this->assertArrayNotHasKey('email', $customers['user1']);
-        $this->assertArrayNotHasKey('address', $customers['user1']);
-        $this->assertArrayNotHasKey('status', $customers['user1']);
-        $this->assertArrayHasKey('id', $customers['user2']);
-        $this->assertArrayHasKey('name', $customers['user2']);
-        $this->assertArrayNotHasKey('email', $customers['user2']);
-        $this->assertArrayNotHasKey('address', $customers['user2']);
-        $this->assertArrayNotHasKey('status', $customers['user2']);
-        $this->assertArrayHasKey('id', $customers['user3']);
-        $this->assertArrayHasKey('name', $customers['user3']);
-        $this->assertArrayNotHasKey('email', $customers['user3']);
-        $this->assertArrayNotHasKey('address', $customers['user3']);
-        $this->assertArrayNotHasKey('status', $customers['user3']);
+        $this->assertArrayHasKey('id', $customers['user1']['fields']);
+        $this->assertArrayHasKey('name', $customers['user1']['fields']);
+        $this->assertArrayNotHasKey('email', $customers['user1']['fields']);
+        $this->assertArrayNotHasKey('address', $customers['user1']['fields']);
+        $this->assertArrayNotHasKey('status', $customers['user1']['fields']);
+        $this->assertArrayHasKey('id', $customers['user2']['fields']);
+        $this->assertArrayHasKey('name', $customers['user2']['fields']);
+        $this->assertArrayNotHasKey('email', $customers['user2']['fields']);
+        $this->assertArrayNotHasKey('address', $customers['user2']['fields']);
+        $this->assertArrayNotHasKey('status', $customers['user2']['fields']);
+        $this->assertArrayHasKey('id', $customers['user3']['fields']);
+        $this->assertArrayHasKey('name', $customers['user3']['fields']);
+        $this->assertArrayNotHasKey('email', $customers['user3']['fields']);
+        $this->assertArrayNotHasKey('address', $customers['user3']['fields']);
+        $this->assertArrayNotHasKey('status', $customers['user3']['fields']);
 
         // indexBy callable + asArray
         $customers = Customer::find()->indexBy(function ($customer) {
-            return $customer['id'] . '-' . $customer['name'];
+            return reset($customer['fields']['id']) . '-' . reset($customer['fields']['name']);
         })->asArray()->fields('id', 'name')->all();
         $this->assertEquals(3, count($customers));
-        $this->assertArrayHasKey('id', $customers['1-user1']);
-        $this->assertArrayHasKey('name', $customers['1-user1']);
-        $this->assertArrayNotHasKey('email', $customers['1-user1']);
-        $this->assertArrayNotHasKey('address', $customers['1-user1']);
-        $this->assertArrayNotHasKey('status', $customers['1-user1']);
-        $this->assertArrayHasKey('id', $customers['2-user2']);
-        $this->assertArrayHasKey('name', $customers['2-user2']);
-        $this->assertArrayNotHasKey('email', $customers['2-user2']);
-        $this->assertArrayNotHasKey('address', $customers['2-user2']);
-        $this->assertArrayNotHasKey('status', $customers['2-user2']);
-        $this->assertArrayHasKey('id', $customers['3-user3']);
-        $this->assertArrayHasKey('name', $customers['3-user3']);
-        $this->assertArrayNotHasKey('email', $customers['3-user3']);
-        $this->assertArrayNotHasKey('address', $customers['3-user3']);
-        $this->assertArrayNotHasKey('status', $customers['3-user3']);
+        $this->assertArrayHasKey('id', $customers['1-user1']['fields']);
+        $this->assertArrayHasKey('name', $customers['1-user1']['fields']);
+        $this->assertArrayNotHasKey('email', $customers['1-user1']['fields']);
+        $this->assertArrayNotHasKey('address', $customers['1-user1']['fields']);
+        $this->assertArrayNotHasKey('status', $customers['1-user1']['fields']);
+        $this->assertArrayHasKey('id', $customers['2-user2']['fields']);
+        $this->assertArrayHasKey('name', $customers['2-user2']['fields']);
+        $this->assertArrayNotHasKey('email', $customers['2-user2']['fields']);
+        $this->assertArrayNotHasKey('address', $customers['2-user2']['fields']);
+        $this->assertArrayNotHasKey('status', $customers['2-user2']['fields']);
+        $this->assertArrayHasKey('id', $customers['3-user3']['fields']);
+        $this->assertArrayHasKey('name', $customers['3-user3']['fields']);
+        $this->assertArrayNotHasKey('email', $customers['3-user3']['fields']);
+        $this->assertArrayNotHasKey('address', $customers['3-user3']['fields']);
+        $this->assertArrayNotHasKey('status', $customers['3-user3']['fields']);
+    }
+
+    public function testFindIndexByAsArray()
+    {
+        /** @var \yii\db\ActiveRecordInterface $customerClass */
+        $customerClass = $this->getCustomerClass();
+
+        /** @var TestCase|ActiveRecordTestTrait $this */
+        // indexBy + asArray
+        $customers = $customerClass::find()->asArray()->indexBy('name')->all();
+        $this->assertEquals(3, count($customers));
+        $this->assertArrayHasKey('id', $customers['user1']['_source']);
+        $this->assertArrayHasKey('name', $customers['user1']['_source']);
+        $this->assertArrayHasKey('email', $customers['user1']['_source']);
+        $this->assertArrayHasKey('address', $customers['user1']['_source']);
+        $this->assertArrayHasKey('status', $customers['user1']['_source']);
+        $this->assertArrayHasKey('id', $customers['user2']['_source']);
+        $this->assertArrayHasKey('name', $customers['user2']['_source']);
+        $this->assertArrayHasKey('email', $customers['user2']['_source']);
+        $this->assertArrayHasKey('address', $customers['user2']['_source']);
+        $this->assertArrayHasKey('status', $customers['user2']['_source']);
+        $this->assertArrayHasKey('id', $customers['user3']['_source']);
+        $this->assertArrayHasKey('name', $customers['user3']['_source']);
+        $this->assertArrayHasKey('email', $customers['user3']['_source']);
+        $this->assertArrayHasKey('address', $customers['user3']['_source']);
+        $this->assertArrayHasKey('status', $customers['user3']['_source']);
+
+        // indexBy callable + asArray
+        $customers = $customerClass::find()->indexBy(function ($customer) {
+            return $customer['_source']['id'] . '-' . $customer['_source']['name'];
+        })->asArray()->all();
+        $this->assertEquals(3, count($customers));
+        $this->assertArrayHasKey('id', $customers['1-user1']['_source']);
+        $this->assertArrayHasKey('name', $customers['1-user1']['_source']);
+        $this->assertArrayHasKey('email', $customers['1-user1']['_source']);
+        $this->assertArrayHasKey('address', $customers['1-user1']['_source']);
+        $this->assertArrayHasKey('status', $customers['1-user1']['_source']);
+        $this->assertArrayHasKey('id', $customers['2-user2']['_source']);
+        $this->assertArrayHasKey('name', $customers['2-user2']['_source']);
+        $this->assertArrayHasKey('email', $customers['2-user2']['_source']);
+        $this->assertArrayHasKey('address', $customers['2-user2']['_source']);
+        $this->assertArrayHasKey('status', $customers['2-user2']['_source']);
+        $this->assertArrayHasKey('id', $customers['3-user3']['_source']);
+        $this->assertArrayHasKey('name', $customers['3-user3']['_source']);
+        $this->assertArrayHasKey('email', $customers['3-user3']['_source']);
+        $this->assertArrayHasKey('address', $customers['3-user3']['_source']);
+        $this->assertArrayHasKey('status', $customers['3-user3']['_source']);
     }
 
     public function testAfterFindGet()
diff --git a/tests/unit/extensions/elasticsearch/ElasticSearchConnectionTest.php b/tests/unit/extensions/elasticsearch/ElasticSearchConnectionTest.php
index b072585..ee44ac9 100644
--- a/tests/unit/extensions/elasticsearch/ElasticSearchConnectionTest.php
+++ b/tests/unit/extensions/elasticsearch/ElasticSearchConnectionTest.php
@@ -20,7 +20,7 @@ class ElasticSearchConnectionTest extends ElasticSearchTestCase
         $connection->open();
         $this->assertNotNull($connection->activeNode);
         $this->assertArrayHasKey('name', reset($connection->nodes));
-        $this->assertArrayHasKey('hostname', reset($connection->nodes));
+//        $this->assertArrayHasKey('hostname', reset($connection->nodes));
         $this->assertArrayHasKey('version', reset($connection->nodes));
         $this->assertArrayHasKey('http_address', reset($connection->nodes));
     }
diff --git a/tests/unit/extensions/elasticsearch/ElasticSearchTestCase.php b/tests/unit/extensions/elasticsearch/ElasticSearchTestCase.php
index bdad9e6..d1a59b8 100644
--- a/tests/unit/extensions/elasticsearch/ElasticSearchTestCase.php
+++ b/tests/unit/extensions/elasticsearch/ElasticSearchTestCase.php
@@ -17,7 +17,7 @@ class ElasticSearchTestCase extends TestCase
     {
         $this->mockApplication();
 
-        $databases = $this->getParam('databases');
+        $databases = self::getParam('databases');
         $params = isset($databases['elasticsearch']) ? $databases['elasticsearch'] : null;
         if ($params === null || !isset($params['dsn'])) {
             $this->markTestSkipped('No elasticsearch server connection configured.');
@@ -40,7 +40,7 @@ class ElasticSearchTestCase extends TestCase
      */
     public function getConnection($reset = true)
     {
-        $databases = $this->getParam('databases');
+        $databases = self::getParam('databases');
         $params = isset($databases['elasticsearch']) ? $databases['elasticsearch'] : [];
         $db = new Connection();
         if ($reset) {
diff --git a/tests/unit/extensions/elasticsearch/QueryBuilderTest.php b/tests/unit/extensions/elasticsearch/QueryBuilderTest.php
index 8238761..bad2387 100644
--- a/tests/unit/extensions/elasticsearch/QueryBuilderTest.php
+++ b/tests/unit/extensions/elasticsearch/QueryBuilderTest.php
@@ -49,7 +49,7 @@ class QueryBuilderTest extends ElasticSearchTestCase
     public function testYiiCanBeFoundByQuery()
     {
         $this->prepareDbData();
-        $queryParts = ['field' => ['title' => 'yii']];
+        $queryParts = ['term' => ['title' => 'yii']];
         $query = new Query();
         $query->from('yiitest', 'article');
         $query->query = $queryParts;
diff --git a/tests/unit/extensions/elasticsearch/QueryTest.php b/tests/unit/extensions/elasticsearch/QueryTest.php
index d631f15..1e853da 100644
--- a/tests/unit/extensions/elasticsearch/QueryTest.php
+++ b/tests/unit/extensions/elasticsearch/QueryTest.php
@@ -40,16 +40,16 @@ class QueryTest extends ElasticSearchTestCase
         $this->assertEquals(['name', 'status'], $query->fields);
 
         $result = $query->one($this->getConnection());
-        $this->assertEquals(2, count($result['_source']));
-        $this->assertArrayHasKey('status', $result['_source']);
-        $this->assertArrayHasKey('name', $result['_source']);
+        $this->assertEquals(2, count($result['fields']));
+        $this->assertArrayHasKey('status', $result['fields']);
+        $this->assertArrayHasKey('name', $result['fields']);
         $this->assertArrayHasKey('_id', $result);
 
         $query->fields([]);
         $this->assertEquals([], $query->fields);
 
         $result = $query->one($this->getConnection());
-        $this->assertEquals([], $result['_source']);
+        $this->assertArrayNotHasKey('fields', $result);
         $this->assertArrayHasKey('_id', $result);
 
         $query->fields(null);
diff --git a/tests/unit/extensions/mongodb/MongoDbTestCase.php b/tests/unit/extensions/mongodb/MongoDbTestCase.php
index 669bf58..00f4033 100644
--- a/tests/unit/extensions/mongodb/MongoDbTestCase.php
+++ b/tests/unit/extensions/mongodb/MongoDbTestCase.php
@@ -34,7 +34,7 @@ class MongoDbTestCase extends TestCase
         if (!extension_loaded('mongo')) {
             $this->markTestSkipped('mongo extension required.');
         }
-        $config = $this->getParam('mongodb');
+        $config = self::getParam('mongodb');
         if (!empty($config)) {
             $this->mongoDbConfig = $config;
         }
diff --git a/tests/unit/extensions/redis/RedisCacheTest.php b/tests/unit/extensions/redis/RedisCacheTest.php
index 6caab91..76025c7 100644
--- a/tests/unit/extensions/redis/RedisCacheTest.php
+++ b/tests/unit/extensions/redis/RedisCacheTest.php
@@ -22,7 +22,7 @@ class RedisCacheTest extends CacheTestCase
      */
     protected function getCacheInstance()
     {
-        $databases = $this->getParam('databases');
+        $databases = self::getParam('databases');
         $params = isset($databases['redis']) ? $databases['redis'] : null;
         if ($params === null) {
             $this->markTestSkipped('No redis server connection configured.');
diff --git a/tests/unit/extensions/redis/RedisTestCase.php b/tests/unit/extensions/redis/RedisTestCase.php
index 5a2d30c..bd35117 100644
--- a/tests/unit/extensions/redis/RedisTestCase.php
+++ b/tests/unit/extensions/redis/RedisTestCase.php
@@ -15,7 +15,7 @@ abstract class RedisTestCase extends TestCase
 {
     protected function setUp()
     {
-        $databases = $this->getParam('databases');
+        $databases = self::getParam('databases');
         $params = isset($databases['redis']) ? $databases['redis'] : null;
         if ($params === null) {
             $this->markTestSkipped('No redis server connection configured.');
@@ -36,7 +36,7 @@ abstract class RedisTestCase extends TestCase
      */
     public function getConnection($reset = true)
     {
-        $databases = $this->getParam('databases');
+        $databases = self::getParam('databases');
         $params = isset($databases['redis']) ? $databases['redis'] : [];
         $db = new Connection($params);
         if ($reset) {
diff --git a/tests/unit/extensions/sphinx/SphinxTestCase.php b/tests/unit/extensions/sphinx/SphinxTestCase.php
index 6c1e5e0..83b0984 100644
--- a/tests/unit/extensions/sphinx/SphinxTestCase.php
+++ b/tests/unit/extensions/sphinx/SphinxTestCase.php
@@ -48,7 +48,7 @@ class SphinxTestCase extends TestCase
         if (!extension_loaded('pdo') || !extension_loaded('pdo_mysql')) {
             $this->markTestSkipped('pdo and pdo_mysql extension are required.');
         }
-        $config = $this->getParam('sphinx');
+        $config = self::getParam('sphinx');
         if (!empty($config)) {
             $this->sphinxConfig = $config['sphinx'];
             $this->dbConfig = $config['db'];
diff --git a/tests/unit/framework/ar/ActiveRecordTestTrait.php b/tests/unit/framework/ar/ActiveRecordTestTrait.php
index e52bb70..5ae9d90 100644
--- a/tests/unit/framework/ar/ActiveRecordTestTrait.php
+++ b/tests/unit/framework/ar/ActiveRecordTestTrait.php
@@ -70,25 +70,6 @@ trait ActiveRecordTestTrait
         $this->assertTrue($customers[1] instanceof $customerClass);
         $this->assertTrue($customers[2] instanceof $customerClass);
 
-        // find all asArray
-        $customers = $customerClass::find()->asArray()->all();
-        $this->assertEquals(3, count($customers));
-        $this->assertArrayHasKey('id', $customers[0]);
-        $this->assertArrayHasKey('name', $customers[0]);
-        $this->assertArrayHasKey('email', $customers[0]);
-        $this->assertArrayHasKey('address', $customers[0]);
-        $this->assertArrayHasKey('status', $customers[0]);
-        $this->assertArrayHasKey('id', $customers[1]);
-        $this->assertArrayHasKey('name', $customers[1]);
-        $this->assertArrayHasKey('email', $customers[1]);
-        $this->assertArrayHasKey('address', $customers[1]);
-        $this->assertArrayHasKey('status', $customers[1]);
-        $this->assertArrayHasKey('id', $customers[2]);
-        $this->assertArrayHasKey('name', $customers[2]);
-        $this->assertArrayHasKey('email', $customers[2]);
-        $this->assertArrayHasKey('address', $customers[2]);
-        $this->assertArrayHasKey('status', $customers[2]);
-
         // find by a single primary key
         $customer = $customerClass::findOne(2);
         $this->assertTrue($customer instanceof $customerClass);
@@ -136,6 +117,25 @@ trait ActiveRecordTestTrait
             'status' => 1,
             'profile_id' => null,
         ], $customer);
+
+        // find all asArray
+        $customers = $customerClass::find()->asArray()->all();
+        $this->assertEquals(3, count($customers));
+        $this->assertArrayHasKey('id', $customers[0]);
+        $this->assertArrayHasKey('name', $customers[0]);
+        $this->assertArrayHasKey('email', $customers[0]);
+        $this->assertArrayHasKey('address', $customers[0]);
+        $this->assertArrayHasKey('status', $customers[0]);
+        $this->assertArrayHasKey('id', $customers[1]);
+        $this->assertArrayHasKey('name', $customers[1]);
+        $this->assertArrayHasKey('email', $customers[1]);
+        $this->assertArrayHasKey('address', $customers[1]);
+        $this->assertArrayHasKey('status', $customers[1]);
+        $this->assertArrayHasKey('id', $customers[2]);
+        $this->assertArrayHasKey('name', $customers[2]);
+        $this->assertArrayHasKey('email', $customers[2]);
+        $this->assertArrayHasKey('address', $customers[2]);
+        $this->assertArrayHasKey('status', $customers[2]);
     }
 
     public function testFindScalar()
diff --git a/tests/unit/framework/caching/DbCacheTest.php b/tests/unit/framework/caching/DbCacheTest.php
index 81bf139..0036ffe 100644
--- a/tests/unit/framework/caching/DbCacheTest.php
+++ b/tests/unit/framework/caching/DbCacheTest.php
@@ -40,7 +40,7 @@ class DbCacheTest extends CacheTestCase
     public function getConnection($reset = true)
     {
         if ($this->_connection === null) {
-            $databases = $this->getParam('databases');
+            $databases = self::getParam('databases');
             $params = $databases['mysql'];
             $db = new \yii\db\Connection;
             $db->dsn = $params['dsn'];
diff --git a/tests/unit/framework/db/DatabaseTestCase.php b/tests/unit/framework/db/DatabaseTestCase.php
index 8bb677b..b66601e 100644
--- a/tests/unit/framework/db/DatabaseTestCase.php
+++ b/tests/unit/framework/db/DatabaseTestCase.php
@@ -16,7 +16,7 @@ abstract class DatabaseTestCase extends TestCase
     protected function setUp()
     {
         parent::setUp();
-        $databases = $this->getParam('databases');
+        $databases = self::getParam('databases');
         $this->database = $databases[$this->driverName];
         $pdo_database = 'pdo_'.$this->driverName;
 
diff --git a/tests/unit/framework/rbac/DbManagerTestCase.php b/tests/unit/framework/rbac/DbManagerTestCase.php
index 4e5334e..150ed7c 100644
--- a/tests/unit/framework/rbac/DbManagerTestCase.php
+++ b/tests/unit/framework/rbac/DbManagerTestCase.php
@@ -1,6 +1,10 @@
 <?php
 namespace yiiunit\framework\rbac;
 
+use Yii;
+use yii\console\Application;
+use yii\console\Controller;
+use yii\console\controllers\MigrateController;
 use yii\db\Connection;
 use yii\rbac\DbManager;
 
@@ -9,70 +13,97 @@ use yii\rbac\DbManager;
  */
 abstract class DbManagerTestCase extends ManagerTestCase
 {
-    protected $database;
-    protected $driverName = 'mysql';
+    protected static $database;
+    protected static $driverName = 'mysql';
 
     /**
      * @var Connection
      */
-    protected $db;
+    protected static $db;
 
-    protected function setUp()
+    protected static function runConsoleAction($route, $params = [])
     {
-        parent::setUp();
-        $databases = $this->getParam('databases');
-        $this->database = $databases[$this->driverName];
-        $pdo_database = 'pdo_'.$this->driverName;
+        if (Yii::$app === null) {
+            new Application([
+                'id' => 'Migrator',
+                'basePath' => '@yiiunit',
+                'components' => [
+                    'db' => static::getConnection(),
+                    'authManager' => '\yii\rbac\DbManager',
+                ],
+            ]);
+        }
+
+        ob_start();
+        $result = Yii::$app->runAction('migrate/up', ['migrationPath' => '@yii/rbac/migrations/', 'interactive' => false]);
+        echo "Result is ".$result;
+        if ($result !== Controller::EXIT_CODE_NORMAL) {
+            ob_end_flush();
+        } else {
+            ob_end_clean();
+        }
+    }
+
+    public static function setUpBeforeClass()
+    {
+        parent::setUpBeforeClass();
+        $databases = static::getParam('databases');
+        static::$database = $databases[static::$driverName];
+        $pdo_database = 'pdo_' . static::$driverName;
 
         if (!extension_loaded('pdo') || !extension_loaded($pdo_database)) {
-            $this->markTestSkipped('pdo and '.$pdo_database.' extension are required.');
+            static::markTestSkipped('pdo and ' . $pdo_database . ' extension are required.');
         }
 
+        static::runConsoleAction('migrate/up', ['migrationPath' => '@yii/rbac/migrations/', 'interactive' => false]);
+    }
+
+    public static function tearDownAfterClass()
+    {
+        static::runConsoleAction('migrate/down', ['migrationPath' => '@yii/rbac/migrations/', 'interactive' => false]);
+        if (static::$db) {
+            static::$db->close();
+        }
+        Yii::$app = null;
+        parent::tearDownAfterClass();
+    }
+
+    protected function setUp()
+    {
+        parent::setUp();
         $this->auth = new DbManager(['db' => $this->getConnection()]);
+
     }
 
     protected function tearDown()
     {
         parent::tearDown();
-        if ($this->db) {
-            $this->db->close();
-        }
-        $this->destroyApplication();
+        $this->auth->removeAll();
     }
 
     /**
-     * @param  boolean $reset whether to clean up the test database
-     * @param  boolean $open whether to open and populate test database
      * @throws \yii\base\InvalidParamException
      * @throws \yii\db\Exception
      * @throws \yii\base\InvalidConfigException
      * @return \yii\db\Connection
      */
-    public function getConnection($reset = true, $open = true)
+    public static function getConnection()
     {
-        if (!$reset && $this->db) {
-            return $this->db;
-        }
-        $db = new Connection;
-        $db->dsn = $this->database['dsn'];
-        if (isset($this->database['username'])) {
-            $db->username = $this->database['username'];
-            $db->password = $this->database['password'];
-        }
-        if (isset($this->database['attributes'])) {
-            $db->attributes = $this->database['attributes'];
-        }
-        if ($open) {
-            $db->open();
-            $lines = explode(';', file_get_contents(\Yii::getAlias('@yii/rbac/schema-'.$this->driverName.'.sql')));
-            foreach ($lines as $line) {
-                if (trim($line) !== '') {
-                    $db->pdo->exec($line);
-                }
+        if (static::$db == null) {
+            $db = new Connection;
+            $db->dsn = static::$database['dsn'];
+            if (isset(static::$database['username'])) {
+                $db->username = static::$database['username'];
+                $db->password = static::$database['password'];
             }
+            if (isset(static::$database['attributes'])) {
+                $db->attributes = static::$database['attributes'];
+            }
+            if (!$db->isActive) {
+                $db->open();
+            }
+            static::$db = $db;
         }
-        $this->db = $db;
-
-        return $db;
+        return static::$db;
     }
 }
diff --git a/tests/unit/framework/rbac/PgSQLManagerTest.php b/tests/unit/framework/rbac/PgSQLManagerTest.php
index fc072c1..4186fe2 100644
--- a/tests/unit/framework/rbac/PgSQLManagerTest.php
+++ b/tests/unit/framework/rbac/PgSQLManagerTest.php
@@ -6,5 +6,5 @@ namespace yiiunit\framework\rbac;
  */
 class PgSQLManagerTest extends DbManagerTestCase
 {
-    protected $driverName = 'pgsql';
+    protected static $driverName = 'pgsql';
 }
diff --git a/tests/unit/framework/rbac/SqliteManagerTest.php b/tests/unit/framework/rbac/SqliteManagerTest.php
index 3bc8529..316c46a 100644
--- a/tests/unit/framework/rbac/SqliteManagerTest.php
+++ b/tests/unit/framework/rbac/SqliteManagerTest.php
@@ -6,5 +6,5 @@ namespace yiiunit\framework\rbac;
  */
 class SqliteManagerTest extends DbManagerTestCase
 {
-    protected $driverName = 'sqlite';
+    protected static $driverName = 'sqlite';
 }