Commit 5164a167 by Carsten Brandt

finalized Query interface + general cleanup

parent 025d36cb
...@@ -12,24 +12,21 @@ use yii\db\ActiveQueryTrait; ...@@ -12,24 +12,21 @@ use yii\db\ActiveQueryTrait;
use yii\helpers\Json; use yii\helpers\Json;
/** /**
* ActiveQuery represents a query associated with an Active Record class. * ActiveQuery represents a [[Query]] associated with an [[ActiveRecord]] class.
* *
* ActiveQuery instances are usually created by [[ActiveRecord::find()]] * ActiveQuery instances are usually created by [[ActiveRecord::find()]].
* and [[ActiveRecord::count()]].
* *
* ActiveQuery mainly provides the following methods to retrieve the query results: * ActiveQuery mainly provides the following methods to retrieve the query results:
* *
* - [[one()]]: returns a single record populated with the first row of data. * - [[one()]]: returns a single record populated with the first row of data.
* - [[all()]]: returns all records based on the query results. * - [[all()]]: returns all records based on the query results.
* - [[count()]]: returns the number of records. * - [[count()]]: returns the number of records.
* - [[sum()]]: returns the sum over the specified column.
* - [[average()]]: returns the average over the specified column.
* - [[min()]]: returns the min over the specified column.
* - [[max()]]: returns the max over the specified column.
* - [[scalar()]]: returns the value of the first column in the first row of the query result. * - [[scalar()]]: returns the value of the first column in the first row of the query result.
* - [[column()]]: returns the value of the first column in the query result.
* - [[exists()]]: returns a value indicating whether the query result has data or not. * - [[exists()]]: returns a value indicating whether the query result has data or not.
* *
* You can use query methods, such as [[where()]], [[limit()]] and [[orderBy()]] to customize the query options. * Because ActiveQuery extends from [[Query]], one can use query methods, such as [[where()]],
* [[orderBy()]] to customize the query options.
* *
* ActiveQuery also provides the following additional query options: * ActiveQuery also provides the following additional query options:
* *
...@@ -83,16 +80,28 @@ class ActiveQuery extends Query implements ActiveQueryInterface ...@@ -83,16 +80,28 @@ class ActiveQuery extends Query implements ActiveQueryInterface
*/ */
public function all($db = null) public function all($db = null)
{ {
$command = $this->createCommand($db); $result = $this->createCommand($db)->search();
$result = $command->search(); if (empty($result['hits']['hits'])) {
if (empty($result['hits'])) {
return []; return [];
} }
$models = $this->createModels($result['hits']); if ($this->fields !== null) {
if ($this->asArray) { foreach ($result['hits']['hits'] as &$row) {
$row['_source'] = isset($row['fields']) ? $row['fields'] : [];
unset($row['fields']);
}
unset($row);
}
if ($this->asArray && $this->indexBy) {
foreach ($result['hits']['hits'] as &$row) {
$row['_source'][ActiveRecord::PRIMARY_KEY_NAME] = $row['_id'];
$row = $row['_source'];
}
}
$models = $this->createModels($result['hits']['hits']);
if ($this->asArray && !$this->indexBy) {
foreach($models as $key => $model) { foreach($models as $key => $model) {
$model['_source'][ActiveRecord::PRIMARY_KEY_NAME] = $model['_id'];
$models[$key] = $model['_source']; $models[$key] = $model['_source'];
$models[$key][ActiveRecord::PRIMARY_KEY_NAME] = $model['_id'];
} }
} }
if (!empty($this->with)) { if (!empty($this->with)) {
...@@ -133,6 +142,28 @@ class ActiveQuery extends Query implements ActiveQueryInterface ...@@ -133,6 +142,28 @@ class ActiveQuery extends Query implements ActiveQueryInterface
/** /**
* @inheritDocs * @inheritDocs
*/ */
public function search($db = null, $options = [])
{
$result = $this->createCommand($db)->search($options);
if (!empty($result['hits']['hits'])) {
$models = $this->createModels($result['hits']['hits']);
if ($this->asArray) {
foreach($models as $key => $model) {
$model['_source'][ActiveRecord::PRIMARY_KEY_NAME] = $model['_id'];
$models[$key] = $model['_source'];
}
}
if (!empty($this->with)) {
$this->findWith($this->with, $models);
}
$result['hits']['hits'] = $models;
}
return $result;
}
/**
* @inheritDocs
*/
public function scalar($field, $db = null) public function scalar($field, $db = null)
{ {
$record = parent::one($db); $record = parent::one($db);
...@@ -154,12 +185,15 @@ class ActiveQuery extends Query implements ActiveQueryInterface ...@@ -154,12 +185,15 @@ class ActiveQuery extends Query implements ActiveQueryInterface
if ($field == ActiveRecord::PRIMARY_KEY_NAME) { if ($field == ActiveRecord::PRIMARY_KEY_NAME) {
$command = $this->createCommand($db); $command = $this->createCommand($db);
$command->queryParts['fields'] = []; $command->queryParts['fields'] = [];
$rows = $command->search()['hits']; $result = $command->search();
$result = []; if (empty($result['hits']['hits'])) {
foreach ($rows as $row) { return [];
$result[] = $row['_id']; }
$column = [];
foreach ($result['hits']['hits'] as $row) {
$column[] = $row['_id'];
} }
return $result; return $column;
} }
return parent::column($field, $db); return parent::column($field, $db);
} }
......
<?php <?php
/** /**
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008 Yii Software LLC * @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
...@@ -377,7 +377,6 @@ class ActiveRecord extends \yii\db\ActiveRecord ...@@ -377,7 +377,6 @@ class ActiveRecord extends \yii\db\ActiveRecord
if ($item['update']['ok']) { if ($item['update']['ok']) {
$n++; $n++;
} }
// TODO might want to update the _version in update()
} }
return $n; return $n;
} }
......
<?php
/**
*
*
* @author Carsten Brandt <mail@cebe.cc>
*/
namespace yii\elasticsearch;
use yii\base\Object;
class Cluster extends Object
{
// TODO implement http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster.html
}
\ No newline at end of file
<?php <?php
/** /**
* @author Carsten Brandt <mail@cebe.cc> * @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/ */
namespace yii\elasticsearch; namespace yii\elasticsearch;
...@@ -16,10 +18,13 @@ use yii\helpers\Json; ...@@ -16,10 +18,13 @@ use yii\helpers\Json;
/** /**
* Class Command * The Command class implements the API for accessing the elasticsearch REST API.
* *
* http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/glossary.html * Check the [elasticsearch guide](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/index.html)
* for details on these commands.
* *
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/ */
class Command extends Component class Command extends Component
{ {
...@@ -61,7 +66,7 @@ class Command extends Component ...@@ -61,7 +66,7 @@ class Command extends Component
$this->type !== null ? $this->type : '_all', $this->type !== null ? $this->type : '_all',
'_search' '_search'
]; ];
return $this->db->get($url, array_merge($this->options, $options), $query)['hits']; return $this->db->get($url, array_merge($this->options, $options), $query);
} }
/** /**
......
<?php <?php
/** /**
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008 Yii Software LLC * @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
......
<?php <?php
/** /**
* * @link http://www.yiiframework.com/
* * @copyright Copyright (c) 2008 Yii Software LLC
* @author Carsten Brandt <mail@cebe.cc> * @license http://www.yiiframework.com/license/
*/ */
namespace yii\elasticsearch; namespace yii\elasticsearch;
use Guzzle\Http\Exception\ClientErrorResponseException; use Guzzle\Http\Exception\ClientErrorResponseException;
use yii\base\Exception; use yii\base\Exception;
use yii\helpers\Json; use yii\helpers\Json;
/**
* Class GuzzleConnection
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class GuzzleConnection extends Connection class GuzzleConnection extends Connection
{ {
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\elasticsearch;
use yii\base\Object;
/**
* Represents an elastic search cluster node.
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class Node extends Object
{
public $host;
public $port;
}
\ No newline at end of file
...@@ -9,6 +9,7 @@ namespace yii\elasticsearch; ...@@ -9,6 +9,7 @@ namespace yii\elasticsearch;
use Yii; use Yii;
use yii\base\Component; use yii\base\Component;
use yii\base\NotSupportedException;
use yii\db\QueryInterface; use yii\db\QueryInterface;
use yii\db\QueryTrait; use yii\db\QueryTrait;
...@@ -49,16 +50,28 @@ class Query extends Component implements QueryInterface ...@@ -49,16 +50,28 @@ class Query extends Component implements QueryInterface
* @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html#_parameters_3 * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html#_parameters_3
*/ */
public $timeout; public $timeout;
/**
* @var array|string The query part of this search query. This is an array or json string that follows the format of
* the elasticsearch [Query DSL](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html).
*/
public $query; public $query;
/**
* @var array|string The filter part of this search query. This is an array or json string that follows the format of
* the elasticsearch [Query DSL](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html).
*/
public $filter; public $filter;
public $facets = []; public $facets = [];
public $facetResults = []; public function init()
{
public $totalCount; parent::init();
// setting the default limit according to elasticsearch defaults
// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html#_parameters_3
if ($this->limit === null) {
$this->limit = 10;
}
}
/** /**
* Creates a DB command that can be used to execute this query. * Creates a DB command that can be used to execute this query.
...@@ -85,8 +98,10 @@ class Query extends Component implements QueryInterface ...@@ -85,8 +98,10 @@ class Query extends Component implements QueryInterface
public function all($db = null) public function all($db = null)
{ {
$result = $this->createCommand($db)->search(); $result = $this->createCommand($db)->search();
// TODO publish facet results if (empty($result['hits']['hits'])) {
$rows = $result['hits']; return [];
}
$rows = $result['hits']['hits'];
if ($this->indexBy === null && $this->fields === null) { if ($this->indexBy === null && $this->fields === null) {
return $rows; return $rows;
} }
...@@ -119,11 +134,10 @@ class Query extends Component implements QueryInterface ...@@ -119,11 +134,10 @@ class Query extends Component implements QueryInterface
{ {
$options['size'] = 1; $options['size'] = 1;
$result = $this->createCommand($db)->search($options); $result = $this->createCommand($db)->search($options);
// TODO publish facet results if (empty($result['hits']['hits'])) {
if (empty($result['hits'])) {
return false; return false;
} }
$record = reset($result['hits']); $record = reset($result['hits']['hits']);
if ($this->fields !== null) { if ($this->fields !== null) {
$record['_source'] = isset($record['fields']) ? $record['fields'] : []; $record['_source'] = isset($record['fields']) ? $record['fields'] : [];
unset($record['fields']); unset($record['fields']);
...@@ -132,6 +146,43 @@ class Query extends Component implements QueryInterface ...@@ -132,6 +146,43 @@ class Query extends Component implements QueryInterface
} }
/** /**
* Executes the query and returns the complete search result including e.g. hits, facets, totalCount.
* @param Connection $db the database connection used to execute the query.
* If this parameter is not given, the `elasticsearch` application component will be used.
* @param array $options The options given with this query. Possible options are:
* - [routing](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search.html#search-routing)
* - [search_type](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-search-type.html)
* @return array the query results.
*/
public function search($db = null, $options = [])
{
$result = $this->createCommand($db)->search($options);
if (!empty($result['hits']['hits']) && ($this->indexBy === null || $this->fields === 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);
}
}
$rows[$key] = $row;
}
$result['hits']['hits'] = $rows;
}
return $result;
}
// TODO add query stats http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search.html#stats-groups
// TODO add scroll/scan http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-search-type.html#scan
/**
* Executes the query and deletes all matching documents. * Executes the query and deletes all matching documents.
* *
* This will not run facet queries. * This will not run facet queries.
...@@ -142,7 +193,8 @@ class Query extends Component implements QueryInterface ...@@ -142,7 +193,8 @@ class Query extends Component implements QueryInterface
*/ */
public function delete($db = null) public function delete($db = null)
{ {
// TODO http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-delete-by-query.html // TODO implement http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-delete-by-query.html
throw new NotSupportedException('Delete by query is not implemented yet.');
} }
/** /**
...@@ -156,7 +208,7 @@ class Query extends Component implements QueryInterface ...@@ -156,7 +208,7 @@ class Query extends Component implements QueryInterface
*/ */
public function scalar($field, $db = null) public function scalar($field, $db = null)
{ {
$record = self::one($db); $record = self::one($db); // TODO limit fields to the one required
if ($record !== false && isset($record['_source'][$field])) { if ($record !== false && isset($record['_source'][$field])) {
return $record['_source'][$field]; return $record['_source'][$field];
} else { } else {
...@@ -175,12 +227,15 @@ class Query extends Component implements QueryInterface ...@@ -175,12 +227,15 @@ class Query extends Component implements QueryInterface
{ {
$command = $this->createCommand($db); $command = $this->createCommand($db);
$command->queryParts['fields'] = [$field]; $command->queryParts['fields'] = [$field];
$rows = $command->search()['hits']; $result = $command->search();
$result = []; if (empty($result['hits']['hits'])) {
foreach ($rows as $row) { return [];
$result[] = isset($row['fields'][$field]) ? $row['fields'][$field] : null;
} }
return $result; $column = [];
foreach ($result['hits']['hits'] as $row) {
$column[] = isset($row['fields'][$field]) ? $row['fields'][$field] : null;
}
return $column;
} }
/** /**
...@@ -198,7 +253,7 @@ class Query extends Component implements QueryInterface ...@@ -198,7 +253,7 @@ class Query extends Component implements QueryInterface
$options = []; $options = [];
$options['search_type'] = 'count'; $options['search_type'] = 'count';
$count = $this->createCommand($db)->search($options)['total']; $count = $this->createCommand($db)->search($options)['hits']['total'];
if ($this->limit === null && $this->offset === null) { if ($this->limit === null && $this->offset === null) {
return $count; return $count;
} elseif ($this->offset !== null) { } elseif ($this->offset !== null) {
...@@ -354,9 +409,26 @@ class Query extends Component implements QueryInterface ...@@ -354,9 +409,26 @@ class Query extends Component implements QueryInterface
// TODO support multi query via static method http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-multi-search.html // TODO support multi query via static method http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-multi-search.html
public function query() /**
* Sets the querypart of this search query.
* @param string $query
* @return static
*/
public function query($query)
{ {
$this->query = $query;
return $this;
}
/**
* Sets the filter part of this search query.
* @param string $filter
* @return static
*/
public function filter($filter)
{
$this->filter = $filter;
return $this;
} }
/** /**
...@@ -381,7 +453,11 @@ class Query extends Component implements QueryInterface ...@@ -381,7 +453,11 @@ class Query extends Component implements QueryInterface
*/ */
public function fields($fields) public function fields($fields)
{ {
$this->fields = $fields; if (is_array($fields)) {
$this->fields = $fields;
} else {
$this->fields = func_get_args();
}
return $this; return $this;
} }
...@@ -397,5 +473,4 @@ class Query extends Component implements QueryInterface ...@@ -397,5 +473,4 @@ class Query extends Component implements QueryInterface
$this->timeout = $timeout; $this->timeout = $timeout;
return $this; return $this;
} }
} }
\ No newline at end of file
...@@ -9,6 +9,7 @@ namespace yii\elasticsearch; ...@@ -9,6 +9,7 @@ namespace yii\elasticsearch;
use yii\base\InvalidParamException; use yii\base\InvalidParamException;
use yii\base\NotSupportedException; use yii\base\NotSupportedException;
use yii\helpers\Json;
/** /**
* QueryBuilder builds an elasticsearch query based on the specification given as a [[Query]] object. * QueryBuilder builds an elasticsearch query based on the specification given as a [[Query]] object.
...@@ -55,13 +56,25 @@ class QueryBuilder extends \yii\base\Object ...@@ -55,13 +56,25 @@ class QueryBuilder extends \yii\base\Object
$parts['from'] = (int) $query->offset; $parts['from'] = (int) $query->offset;
} }
$filters = empty($query->filter) ? [] : [$query->filter]; if (empty($parts['query'])) {
$whereFilter = $this->buildCondition($query->where); $parts['query'] = ["match_all" => (object)[]];
if (!empty($whereFilter)) {
$filters[] = $whereFilter;
} }
if (!empty($filters)) {
$parts['filter'] = count($filters) > 1 ? ['and' => $filters] : $filters[0]; $whereFilter = $this->buildCondition($query->where);
if (is_string($query->filter)) {
if (empty($whereFilter)) {
$parts['filter'] = $query->filter;
} else {
$parts['filter'] = '{"and": [' . $query->filter . ', ' . Json::encode($whereFilter) . ']}';
}
} elseif ($query->filter !== null) {
if (empty($whereFilter)) {
$parts['filter'] = $query->filter;
} else {
$parts['filter'] = ['and' => [$query->filter, $whereFilter]];
}
} elseif (!empty($whereFilter)) {
$parts['filter'] = $whereFilter;
} }
$sort = $this->buildOrderBy($query->orderBy); $sort = $this->buildOrderBy($query->orderBy);
...@@ -69,8 +82,8 @@ class QueryBuilder extends \yii\base\Object ...@@ -69,8 +82,8 @@ class QueryBuilder extends \yii\base\Object
$parts['sort'] = $sort; $parts['sort'] = $sort;
} }
if (empty($parts['query'])) { if (!empty($query->facets)) {
$parts['query'] = ["match_all" => (object)[]]; $parts['facets'] = $query->facets;
} }
$options = []; $options = [];
......
...@@ -23,6 +23,7 @@ namespace yii\db; ...@@ -23,6 +23,7 @@ namespace yii\db;
* - [[min()]]: returns the min over the specified column. * - [[min()]]: returns the min over the specified column.
* - [[max()]]: returns the max over the specified column. * - [[max()]]: returns the max over the specified column.
* - [[scalar()]]: returns the value of the first column in the first row of the query result. * - [[scalar()]]: returns the value of the first column in the first row of the query result.
* - [[column()]]: returns the value of the first column in the query result.
* - [[exists()]]: returns a value indicating whether the query result has data or not. * - [[exists()]]: returns a value indicating whether the query result has data or not.
* *
* Because ActiveQuery extends from [[Query]], one can use query methods, such as [[where()]], * Because ActiveQuery extends from [[Query]], one can use query methods, such as [[where()]],
......
...@@ -132,6 +132,62 @@ class ActiveRecordTest extends ElasticSearchTestCase ...@@ -132,6 +132,62 @@ class ActiveRecordTest extends ElasticSearchTestCase
$db->createCommand()->flushIndex('yiitest'); $db->createCommand()->flushIndex('yiitest');
} }
public function testSearch()
{
$customers = $this->callCustomerFind()->search()['hits'];
$this->assertEquals(3, $customers['total']);
$this->assertEquals(3, count($customers['hits']));
$this->assertTrue($customers['hits'][0] instanceof Customer);
$this->assertTrue($customers['hits'][1] instanceof Customer);
$this->assertTrue($customers['hits'][2] instanceof Customer);
// limit vs. totalcount
$customers = $this->callCustomerFind()->limit(2)->search()['hits'];
$this->assertEquals(3, $customers['total']);
$this->assertEquals(2, count($customers['hits']));
// asArray
$result = $this->callCustomerFind()->asArray()->search()['hits'];
$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]);
// TODO test asArray() + fields() + indexBy()
// find by attributes
$result = $this->callCustomerFind()->where(['name' => 'user2'])->search()['hits'];
$customer = reset($result['hits']);
$this->assertTrue($customer instanceof Customer);
$this->assertEquals(2, $customer->id);
// TODO test query() and filter()
}
public function testSearchFacets()
{
$result = $this->callCustomerFind()->addStatisticalFacet('status_stats', ['field' => 'status'])->search();
$this->assertArrayHasKey('facets', $result);
$this->assertEquals(3, $result['facets']['status_stats']['count']);
$this->assertEquals(4, $result['facets']['status_stats']['total']); // sum of values
$this->assertEquals(1, $result['facets']['status_stats']['min']);
$this->assertEquals(2, $result['facets']['status_stats']['max']);
}
public function testGetDb() public function testGetDb()
{ {
$this->mockApplication(['components' => ['elasticsearch' => Connection::className()]]); $this->mockApplication(['components' => ['elasticsearch' => Connection::className()]]);
...@@ -314,4 +370,126 @@ class ActiveRecordTest extends ElasticSearchTestCase ...@@ -314,4 +370,126 @@ class ActiveRecordTest extends ElasticSearchTestCase
$customers = $this->callCustomerFind()->where(['status' => false])->all(); $customers = $this->callCustomerFind()->where(['status' => false])->all();
$this->assertEquals(2, count($customers)); $this->assertEquals(2, count($customers));
} }
public function testfindAsArrayFields()
{
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy + asArray
$customers = $this->callCustomerFind()->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]);
}
public function testfindIndexByFields()
{
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy + asArray
$customers = $this->callCustomerFind()->indexBy('name')->fields('id', 'name')->all();
$this->assertEquals(3, count($customers));
$this->assertTrue($customers['user1'] instanceof $customerClass);
$this->assertTrue($customers['user2'] instanceof $customerClass);
$this->assertTrue($customers['user3'] instanceof $customerClass);
$this->assertNotNull($customers['user1']->id);
$this->assertNotNull($customers['user1']->name);
$this->assertNull($customers['user1']->email);
$this->assertNull($customers['user1']->address);
$this->assertNull($customers['user1']->status);
$this->assertNotNull($customers['user2']->id);
$this->assertNotNull($customers['user2']->name);
$this->assertNull($customers['user2']->email);
$this->assertNull($customers['user2']->address);
$this->assertNull($customers['user2']->status);
$this->assertNotNull($customers['user3']->id);
$this->assertNotNull($customers['user3']->name);
$this->assertNull($customers['user3']->email);
$this->assertNull($customers['user3']->address);
$this->assertNull($customers['user3']->status);
// indexBy callable + asArray
$customers = $this->callCustomerFind()->indexBy(function ($customer) {
return $customer->id . '-' . $customer->name;
})->fields('id', 'name')->all();
$this->assertEquals(3, count($customers));
$this->assertTrue($customers['1-user1'] instanceof $customerClass);
$this->assertTrue($customers['2-user2'] instanceof $customerClass);
$this->assertTrue($customers['3-user3'] instanceof $customerClass);
$this->assertNotNull($customers['1-user1']->id);
$this->assertNotNull($customers['1-user1']->name);
$this->assertNull($customers['1-user1']->email);
$this->assertNull($customers['1-user1']->address);
$this->assertNull($customers['1-user1']->status);
$this->assertNotNull($customers['2-user2']->id);
$this->assertNotNull($customers['2-user2']->name);
$this->assertNull($customers['2-user2']->email);
$this->assertNull($customers['2-user2']->address);
$this->assertNull($customers['2-user2']->status);
$this->assertNotNull($customers['3-user3']->id);
$this->assertNotNull($customers['3-user3']->name);
$this->assertNull($customers['3-user3']->email);
$this->assertNull($customers['3-user3']->address);
$this->assertNull($customers['3-user3']->status);
}
public function testfindIndexByAsArrayFields()
{
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy + asArray
$customers = $this->callCustomerFind()->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']);
// indexBy callable + asArray
$customers = $this->callCustomerFind()->indexBy(function ($customer) {
return $customer['id'] . '-' . $customer['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']);
}
} }
\ No newline at end of file
...@@ -199,6 +199,51 @@ trait ActiveRecordTestTrait ...@@ -199,6 +199,51 @@ trait ActiveRecordTestTrait
$this->assertTrue($customers['3-user3'] instanceof $customerClass); $this->assertTrue($customers['3-user3'] instanceof $customerClass);
} }
public function testfindIndexByAsArray()
{
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy + asArray
$customers = $this->callCustomerFind()->asArray()->indexBy('name')->all();
$this->assertEquals(3, count($customers));
$this->assertArrayHasKey('id', $customers['user1']);
$this->assertArrayHasKey('name', $customers['user1']);
$this->assertArrayHasKey('email', $customers['user1']);
$this->assertArrayHasKey('address', $customers['user1']);
$this->assertArrayHasKey('status', $customers['user1']);
$this->assertArrayHasKey('id', $customers['user2']);
$this->assertArrayHasKey('name', $customers['user2']);
$this->assertArrayHasKey('email', $customers['user2']);
$this->assertArrayHasKey('address', $customers['user2']);
$this->assertArrayHasKey('status', $customers['user2']);
$this->assertArrayHasKey('id', $customers['user3']);
$this->assertArrayHasKey('name', $customers['user3']);
$this->assertArrayHasKey('email', $customers['user3']);
$this->assertArrayHasKey('address', $customers['user3']);
$this->assertArrayHasKey('status', $customers['user3']);
// indexBy callable + asArray
$customers = $this->callCustomerFind()->indexBy(function ($customer) {
return $customer['id'] . '-' . $customer['name'];
})->asArray()->all();
$this->assertEquals(3, count($customers));
$this->assertArrayHasKey('id', $customers['1-user1']);
$this->assertArrayHasKey('name', $customers['1-user1']);
$this->assertArrayHasKey('email', $customers['1-user1']);
$this->assertArrayHasKey('address', $customers['1-user1']);
$this->assertArrayHasKey('status', $customers['1-user1']);
$this->assertArrayHasKey('id', $customers['2-user2']);
$this->assertArrayHasKey('name', $customers['2-user2']);
$this->assertArrayHasKey('email', $customers['2-user2']);
$this->assertArrayHasKey('address', $customers['2-user2']);
$this->assertArrayHasKey('status', $customers['2-user2']);
$this->assertArrayHasKey('id', $customers['3-user3']);
$this->assertArrayHasKey('name', $customers['3-user3']);
$this->assertArrayHasKey('email', $customers['3-user3']);
$this->assertArrayHasKey('address', $customers['3-user3']);
$this->assertArrayHasKey('status', $customers['3-user3']);
}
public function testRefresh() public function testRefresh()
{ {
$customerClass = $this->getCustomerClass(); $customerClass = $this->getCustomerClass();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment