Commit e2b4708b by Carsten Brandt

added support for updateCounters to elasticsearch

issue #1313
parent 8ce2f170
...@@ -340,10 +340,9 @@ class ActiveRecord extends BaseActiveRecord ...@@ -340,10 +340,9 @@ class ActiveRecord extends BaseActiveRecord
* @param array $attributes attribute values (name-value pairs) to be saved into the table * @param array $attributes attribute values (name-value pairs) to be saved into the table
* @param array $condition the conditions that will be put in the WHERE part of the UPDATE SQL. * @param array $condition the conditions that will be put in the WHERE part of the UPDATE SQL.
* Please refer to [[ActiveQuery::where()]] on how to specify this parameter. * Please refer to [[ActiveQuery::where()]] on how to specify this parameter.
* @param array $params this parameter is ignored in elasticsearch implementation.
* @return integer the number of rows updated * @return integer the number of rows updated
*/ */
public static function updateAll($attributes, $condition = [], $params = []) public static function updateAll($attributes, $condition = [])
{ {
if (count($condition) == 1 && isset($condition[ActiveRecord::PRIMARY_KEY_NAME])) { if (count($condition) == 1 && isset($condition[ActiveRecord::PRIMARY_KEY_NAME])) {
$primaryKeys = (array) $condition[ActiveRecord::PRIMARY_KEY_NAME]; $primaryKeys = (array) $condition[ActiveRecord::PRIMARY_KEY_NAME];
...@@ -362,9 +361,9 @@ class ActiveRecord extends BaseActiveRecord ...@@ -362,9 +361,9 @@ class ActiveRecord extends BaseActiveRecord
"_index" => static::index(), "_index" => static::index(),
], ],
]); ]);
$data = Json::encode(array( $data = Json::encode([
"doc" => $attributes "doc" => $attributes
)); ]);
$bulk .= $action . "\n" . $data . "\n"; $bulk .= $action . "\n" . $data . "\n";
} }
...@@ -380,6 +379,62 @@ class ActiveRecord extends BaseActiveRecord ...@@ -380,6 +379,62 @@ class ActiveRecord extends BaseActiveRecord
return $n; return $n;
} }
/**
* Updates all matching records using the provided counter changes and conditions.
* For example, to increment all customers' age by 1,
*
* ~~~
* Customer::updateAllCounters(['age' => 1]);
* ~~~
*
* @param array $counters the counters to be updated (attribute name => increment value).
* Use negative values if you want to decrement the counters.
* @param string|array $condition the conditions that will be put in the WHERE part of the UPDATE SQL.
* Please refer to [[Query::where()]] on how to specify this parameter.
* @return integer the number of rows updated
*/
public static function updateAllCounters($counters, $condition = [])
{
if (count($condition) == 1 && isset($condition[ActiveRecord::PRIMARY_KEY_NAME])) {
$primaryKeys = (array) $condition[ActiveRecord::PRIMARY_KEY_NAME];
} else {
$primaryKeys = static::find()->where($condition)->column(ActiveRecord::PRIMARY_KEY_NAME);
}
if (empty($primaryKeys) || empty($counters)) {
return 0;
}
$bulk = '';
foreach((array) $primaryKeys as $pk) {
$action = Json::encode([
"update" => [
"_id" => $pk,
"_type" => static::type(),
"_index" => static::index(),
],
]);
$script = '';
foreach($counters as $counter => $value) {
$script .= "ctx._source.$counter += $counter;\n";
}
$data = Json::encode([
"script" => $script,
"params" => $counters
]);
$bulk .= $action . "\n" . $data . "\n";
}
// TODO do this via command
$url = [static::index(), static::type(), '_bulk'];
$response = static::getDb()->post($url, [], $bulk);
$n=0;
foreach($response['items'] as $item) {
if ($item['update']['ok']) {
$n++;
}
}
return $n;
}
/** /**
* Deletes rows in the table using the provided conditions. * Deletes rows in the table using the provided conditions.
...@@ -393,10 +448,9 @@ class ActiveRecord extends BaseActiveRecord ...@@ -393,10 +448,9 @@ class ActiveRecord extends BaseActiveRecord
* *
* @param array $condition the conditions that will be put in the WHERE part of the DELETE SQL. * @param array $condition the conditions that will be put in the WHERE part of the DELETE SQL.
* Please refer to [[ActiveQuery::where()]] on how to specify this parameter. * Please refer to [[ActiveQuery::where()]] on how to specify this parameter.
* @param array $params this parameter is ignored in elasticsearch implementation.
* @return integer the number of rows deleted * @return integer the number of rows deleted
*/ */
public static function deleteAll($condition = [], $params = []) public static function deleteAll($condition = [])
{ {
if (count($condition) == 1 && isset($condition[ActiveRecord::PRIMARY_KEY_NAME])) { if (count($condition) == 1 && isset($condition[ActiveRecord::PRIMARY_KEY_NAME])) {
$primaryKeys = (array) $condition[ActiveRecord::PRIMARY_KEY_NAME]; $primaryKeys = (array) $condition[ActiveRecord::PRIMARY_KEY_NAME];
......
...@@ -150,10 +150,9 @@ class ActiveRecord extends BaseActiveRecord ...@@ -150,10 +150,9 @@ class ActiveRecord extends BaseActiveRecord
* @param array $attributes attribute values (name-value pairs) to be saved into the table * @param array $attributes attribute values (name-value pairs) to be saved into the table
* @param array $condition the conditions that will be put in the WHERE part of the UPDATE SQL. * @param array $condition the conditions that will be put in the WHERE part of the UPDATE SQL.
* Please refer to [[ActiveQuery::where()]] on how to specify this parameter. * Please refer to [[ActiveQuery::where()]] on how to specify this parameter.
* @param array $params this parameter is ignored in redis implementation.
* @return integer the number of rows updated * @return integer the number of rows updated
*/ */
public static function updateAll($attributes, $condition = null, $params = []) public static function updateAll($attributes, $condition = null)
{ {
if (empty($attributes)) { if (empty($attributes)) {
return 0; return 0;
...@@ -203,10 +202,9 @@ class ActiveRecord extends BaseActiveRecord ...@@ -203,10 +202,9 @@ class ActiveRecord extends BaseActiveRecord
* Use negative values if you want to decrement the counters. * Use negative values if you want to decrement the counters.
* @param array $condition the conditions that will be put in the WHERE part of the UPDATE SQL. * @param array $condition the conditions that will be put in the WHERE part of the UPDATE SQL.
* Please refer to [[ActiveQuery::where()]] on how to specify this parameter. * Please refer to [[ActiveQuery::where()]] on how to specify this parameter.
* @param array $params this parameter is ignored in redis implementation.
* @return integer the number of rows updated * @return integer the number of rows updated
*/ */
public static function updateAllCounters($counters, $condition = null, $params = []) public static function updateAllCounters($counters, $condition = null)
{ {
if (empty($counters)) { if (empty($counters)) {
return 0; return 0;
...@@ -235,10 +233,9 @@ class ActiveRecord extends BaseActiveRecord ...@@ -235,10 +233,9 @@ class ActiveRecord extends BaseActiveRecord
* *
* @param array $condition the conditions that will be put in the WHERE part of the DELETE SQL. * @param array $condition the conditions that will be put in the WHERE part of the DELETE SQL.
* Please refer to [[ActiveQuery::where()]] on how to specify this parameter. * Please refer to [[ActiveQuery::where()]] on how to specify this parameter.
* @param array $params this parameter is ignored in redis implementation.
* @return integer the number of rows deleted * @return integer the number of rows deleted
*/ */
public static function deleteAll($condition = null, $params = []) public static function deleteAll($condition = null)
{ {
$db = static::getDb(); $db = static::getDb();
$attributeKeys = []; $attributeKeys = [];
......
...@@ -158,8 +158,6 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface ...@@ -158,8 +158,6 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
* Use negative values if you want to decrement the counters. * Use negative values if you want to decrement the counters.
* @param string|array $condition the conditions that will be put in the WHERE part of the UPDATE SQL. * @param string|array $condition the conditions that will be put in the WHERE part of the UPDATE SQL.
* Please refer to [[Query::where()]] on how to specify this parameter. * Please refer to [[Query::where()]] on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
* Do not name the parameters as `:bp0`, `:bp1`, etc., because they are used internally by this method.
* @return integer the number of rows updated * @return integer the number of rows updated
*/ */
public static function updateAllCounters($counters, $condition = '') public static function updateAllCounters($counters, $condition = '')
......
...@@ -313,13 +313,6 @@ class ActiveRecordTest extends ElasticSearchTestCase ...@@ -313,13 +313,6 @@ class ActiveRecordTest extends ElasticSearchTestCase
$this->assertEquals([], $order->items); $this->assertEquals([], $order->items);
} }
public function testUpdateCounters()
{
// Update Counters is not supported by elasticsearch
// $this->setExpectedException('yii\base\NotSupportedException');
// ActiveRecordTestTrait::testUpdateCounters();
}
/** /**
* Some PDO implementations(e.g. cubrid) do not support boolean values. * Some PDO implementations(e.g. cubrid) do not support boolean values.
* Make sure this does not affect AR layer. * Make sure this does not affect AR layer.
......
...@@ -670,7 +670,7 @@ trait ActiveRecordTestTrait ...@@ -670,7 +670,7 @@ trait ActiveRecordTestTrait
$this->assertEquals(1, $orderItem->quantity); $this->assertEquals(1, $orderItem->quantity);
$ret = $orderItem->updateCounters(['quantity' => -1]); $ret = $orderItem->updateCounters(['quantity' => -1]);
$this->afterSave(); $this->afterSave();
$this->assertTrue($ret); $this->assertEquals(1, $ret);
$this->assertEquals(0, $orderItem->quantity); $this->assertEquals(0, $orderItem->quantity);
$orderItem = $this->callOrderItemFind($pk); $orderItem = $this->callOrderItemFind($pk);
$this->assertEquals(0, $orderItem->quantity); $this->assertEquals(0, $orderItem->quantity);
......
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