Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
39ff11a3
Commit
39ff11a3
authored
Nov 23, 2013
by
Carsten Brandt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
first draft of elasticsearch AR
parent
9f121853
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
397 additions
and
711 deletions
+397
-711
ActiveQuery.php
framework/yii/elasticsearch/ActiveQuery.php
+23
-35
ActiveRecord.php
framework/yii/elasticsearch/ActiveRecord.php
+197
-230
Command.php
framework/yii/elasticsearch/Command.php
+38
-88
Query.php
framework/yii/elasticsearch/Query.php
+99
-308
ActiveRecord.php
framework/yii/redis/ActiveRecord.php
+2
-2
Customer.php
tests/unit/data/ar/elasticsearch/Customer.php
+2
-8
Item.php
tests/unit/data/ar/elasticsearch/Item.php
+2
-6
Order.php
tests/unit/data/ar/elasticsearch/Order.php
+8
-13
OrderItem.php
tests/unit/data/ar/elasticsearch/OrderItem.php
+4
-9
ActiveRecordTest.php
tests/unit/framework/elasticsearch/ActiveRecordTest.php
+22
-12
No files found.
framework/yii/elasticsearch/ActiveQuery.php
View file @
39ff11a3
...
@@ -58,31 +58,21 @@ class ActiveQuery extends Query implements ActiveQueryInterface
...
@@ -58,31 +58,21 @@ class ActiveQuery extends Query implements ActiveQueryInterface
*/
*/
public
function
createCommand
(
$db
=
null
)
public
function
createCommand
(
$db
=
null
)
{
{
/** @var
$modelClass ActiveRecord
*/
/** @var
ActiveRecord $modelClass
*/
$modelClass
=
$this
->
modelClass
;
$modelClass
=
$this
->
modelClass
;
if
(
$db
===
null
)
{
if
(
$db
===
null
)
{
$db
=
$modelClass
::
getDb
();
$db
=
$modelClass
::
getDb
();
}
}
$index
=
$modelClass
::
indexName
();
if
(
$this
->
type
===
null
)
{
$type
=
$modelClass
::
indexType
();
$this
->
type
=
$modelClass
::
type
();
if
(
is_array
(
$this
->
where
)
&&
Activerecord
::
isPrimaryKey
(
array_keys
(
$this
->
where
)))
{
// TODO what about mixed queries?
$query
=
array
();
foreach
((
array
)
reset
(
$this
->
where
)
as
$pk
)
{
$doc
=
array
(
'_id'
=>
$pk
,
);
$db
->
getQueryBuilder
()
->
buildSelect
(
$doc
,
$this
->
select
);
$query
[
'docs'
][]
=
$doc
;
}
}
$command
=
$db
->
createCommand
(
$query
,
$index
,
$type
);
if
(
$this
->
index
===
null
)
{
$command
->
api
=
'_mget'
;
$this
->
index
=
$modelClass
::
index
();
return
$command
;
$this
->
type
=
$modelClass
::
type
();
}
else
{
$query
=
$db
->
getQueryBuilder
()
->
build
(
$this
);
return
$db
->
createCommand
(
$query
,
$index
,
$type
);
}
}
$query
=
$db
->
getQueryBuilder
()
->
build
(
$this
);
return
$db
->
createCommand
(
$query
,
$this
->
index
,
$this
->
type
);
}
}
/**
/**
...
@@ -94,16 +84,15 @@ class ActiveQuery extends Query implements ActiveQueryInterface
...
@@ -94,16 +84,15 @@ class ActiveQuery extends Query implements ActiveQueryInterface
public
function
all
(
$db
=
null
)
public
function
all
(
$db
=
null
)
{
{
$command
=
$this
->
createCommand
(
$db
);
$command
=
$this
->
createCommand
(
$db
);
$rows
=
$command
->
queryAll
();
$result
=
$command
->
queryAll
();
if
(
!
empty
(
$rows
))
{
if
(
$result
[
'total'
]
==
0
)
{
$models
=
$this
->
createModels
(
$rows
);
return
[];
}
$models
=
$this
->
createModels
(
$result
[
'hits'
]);
if
(
!
empty
(
$this
->
with
))
{
if
(
!
empty
(
$this
->
with
))
{
$this
->
populateRelations
(
$models
,
$this
->
with
);
$this
->
findWith
(
$this
->
with
,
$models
);
}
}
return
$models
;
return
$models
;
}
else
{
return
array
();
}
}
}
/**
/**
...
@@ -117,23 +106,22 @@ class ActiveQuery extends Query implements ActiveQueryInterface
...
@@ -117,23 +106,22 @@ class ActiveQuery extends Query implements ActiveQueryInterface
public
function
one
(
$db
=
null
)
public
function
one
(
$db
=
null
)
{
{
$command
=
$this
->
createCommand
(
$db
);
$command
=
$this
->
createCommand
(
$db
);
$row
=
$command
->
queryOne
();
$result
=
$command
->
queryOne
();
if
(
$row
!==
false
)
{
if
(
$result
[
'total'
]
==
0
)
{
return
null
;
}
if
(
$this
->
asArray
)
{
if
(
$this
->
asArray
)
{
$model
=
$row
;
$model
=
reset
(
$result
[
'hits'
])
;
}
else
{
}
else
{
/** @var $class ActiveRecord
*/
/** @var ActiveRecord $class
*/
$class
=
$this
->
modelClass
;
$class
=
$this
->
modelClass
;
$model
=
$class
::
create
(
$row
);
$model
=
$class
::
create
(
reset
(
$result
[
'hits'
])
);
}
}
if
(
!
empty
(
$this
->
with
))
{
if
(
!
empty
(
$this
->
with
))
{
$models
=
array
(
$model
)
;
$models
=
[
$model
]
;
$this
->
populateRelations
(
$models
,
$this
->
with
);
$this
->
findWith
(
$this
->
with
,
$models
);
$model
=
$models
[
0
];
$model
=
$models
[
0
];
}
}
return
$model
;
return
$model
;
}
else
{
return
null
;
}
}
}
}
}
framework/yii/elasticsearch/ActiveRecord.php
View file @
39ff11a3
...
@@ -9,15 +9,14 @@ namespace yii\elasticsearch;
...
@@ -9,15 +9,14 @@ namespace yii\elasticsearch;
use
yii\base\InvalidCallException
;
use
yii\base\InvalidCallException
;
use
yii\base\InvalidConfigException
;
use
yii\base\InvalidConfigException
;
use
yii\base\InvalidParamException
;
use
yii\base\NotSupportedException
;
use
yii\base\NotSupportedException
;
use
yii\base\UnknownMethodException
;
use
yii\db\Exception
;
use
yii\db\TableSchema
;
use
yii\db\TableSchema
;
use
yii\helpers\Inflector
;
use
yii\helpers\Inflector
;
use
yii\helpers\Json
;
use
yii\helpers\Json
;
use
yii\helpers\StringHelper
;
use
yii\helpers\StringHelper
;
// TODO handle optimistic lock
/**
/**
* ActiveRecord is the base class for classes representing relational data in terms of objects.
* ActiveRecord is the base class for classes representing relational data in terms of objects.
*
*
...
@@ -28,6 +27,9 @@ use yii\helpers\StringHelper;
...
@@ -28,6 +27,9 @@ use yii\helpers\StringHelper;
*/
*/
abstract
class
ActiveRecord
extends
\yii\db\ActiveRecord
abstract
class
ActiveRecord
extends
\yii\db\ActiveRecord
{
{
private
$_id
;
private
$_version
;
/**
/**
* Returns the database connection used by this AR class.
* Returns the database connection used by this AR class.
* By default, the "elasticsearch" application component is used as the database connection.
* By default, the "elasticsearch" application component is used as the database connection.
...
@@ -40,20 +42,167 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord
...
@@ -40,20 +42,167 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord
}
}
/**
/**
* @inheritdoc
* @inheritDoc
*/
public
static
function
find
(
$q
=
null
)
{
$query
=
static
::
createQuery
();
if
(
is_array
(
$q
))
{
if
(
count
(
$q
)
==
1
&&
isset
(
$q
[
'primaryKey'
]))
{
return
static
::
get
(
$q
[
'primaryKey'
]);
}
return
$query
->
where
(
$q
)
->
one
();
}
elseif
(
$q
!==
null
)
{
return
static
::
get
(
$q
);
}
return
$query
;
}
public
static
function
get
(
$primaryKey
,
$options
=
[])
{
$command
=
static
::
getDb
()
->
createCommand
();
$result
=
$command
->
get
(
static
::
index
(),
static
::
type
(),
$primaryKey
,
$options
);
if
(
$result
[
'exists'
])
{
return
static
::
create
(
$result
);
}
return
null
;
}
/**
* @inheritDoc
*/
public
static
function
createQuery
()
{
return
new
ActiveQuery
([
'modelClass'
=>
get_called_class
()]);
}
/**
* @inheritDoc
*/
public
static
function
createActiveRelation
(
$config
=
[])
{
return
new
ActiveRelation
(
$config
);
}
// TODO implement copy and move as pk change is not possible
/**
* Sets the primary key
* @param mixed $value
* @throws \yii\base\InvalidCallException when record is not new
*/
public
function
setPrimaryKey
(
$value
)
{
if
(
$this
->
isNewRecord
)
{
$this
->
_id
=
$value
;
}
else
{
throw
new
InvalidCallException
(
'Changing the primaryKey of an already saved record is not allowed.'
);
}
}
/**
* @inheritDoc
*/
*/
public
static
function
findBySql
(
$sql
,
$params
=
array
()
)
public
function
getPrimaryKey
(
$asArray
=
false
)
{
{
throw
new
NotSupportedException
(
'findBySql() is not supported by elasticsearch ActiveRecord'
);
if
(
$asArray
)
{
return
[
'primaryKey'
=>
$this
->
_id
];
}
else
{
return
$this
->
_id
;
}
}
}
/**
* @inheritDoc
*/
public
function
getOldPrimaryKey
(
$asArray
=
false
)
{
return
$this
->
getPrimaryKey
(
$asArray
);
}
/**
/**
* Updates the whole table using the provided attribute values and conditions.
* This method defines the primary.
*
* The primaryKey for elasticsearch documents is always `primaryKey`. It can not be changed.
*
* @return string[] the primary keys of this record.
*/
public
static
function
primaryKey
()
{
return
[
'primaryKey'
];
}
/**
* Returns the list of all attribute names of the model.
* This method must be overridden by child classes to define available attributes.
* @return array list of attribute names.
*/
public
static
function
attributes
()
{
throw
new
InvalidConfigException
(
'The attributes() method of elasticsearch ActiveRecord has to be implemented by child classes.'
);
}
// TODO index and type definition
public
static
function
index
()
{
return
Inflector
::
pluralize
(
Inflector
::
camel2id
(
StringHelper
::
basename
(
get_called_class
()),
'-'
));
}
public
static
function
type
()
{
return
Inflector
::
camel2id
(
StringHelper
::
basename
(
get_called_class
()),
'-'
);
}
/**
* Creates an active record object using a row of data.
* This method is called by [[ActiveQuery]] to populate the query results
* into Active Records. It is not meant to be used to create new records.
* @param array $row attribute values (name => value)
* @return ActiveRecord the newly created active record.
*/
public
static
function
create
(
$row
)
{
$row
[
'_source'
][
'primaryKey'
]
=
$row
[
'_id'
];
$record
=
parent
::
create
(
$row
[
'_source'
]);
return
$record
;
}
/**
* @inheritDocs
*/
public
function
insert
(
$runValidation
=
true
,
$attributes
=
null
)
{
if
(
$runValidation
&&
!
$this
->
validate
(
$attributes
))
{
return
false
;
}
if
(
$this
->
beforeSave
(
true
))
{
$values
=
$this
->
getDirtyAttributes
(
$attributes
);
$response
=
static
::
getDb
()
->
createCommand
()
->
insert
(
static
::
index
(),
static
::
type
(),
$values
,
$this
->
getPrimaryKey
()
);
if
(
!
$response
[
'ok'
])
{
return
false
;
}
$this
->
_id
=
$response
[
'_id'
];
$this
->
_version
=
$response
[
'_version'
];
$this
->
setOldAttributes
(
$values
);
$this
->
afterSave
(
true
);
return
true
;
}
return
false
;
}
/**
* Updates all records whos primary keys are given.
* For example, to change the status to be 1 for all customers whose status is 2:
* For example, to change the status to be 1 for all customers whose status is 2:
*
*
* ~~~
* ~~~
* Customer::updateAll(array('status' => 1), array(
'id' => 2
));
* Customer::updateAll(array('status' => 1), array(
2, 3, 4
));
* ~~~
* ~~~
*
*
* @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
...
@@ -62,67 +211,37 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord
...
@@ -62,67 +211,37 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord
* @param array $params this parameter is ignored in redis implementation.
* @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
=
array
()
)
public
static
function
updateAll
(
$attributes
,
$condition
=
[],
$params
=
[]
)
{
{
// TODO add support for further options as described in http://www.elasticsearch.org/guide/reference/api/bulk/
$bulk
=
''
;
if
(
empty
(
$attributes
))
{
foreach
((
array
)
$condition
as
$pk
)
{
return
0
;
$action
=
Json
::
encode
([
}
"update"
=>
[
if
(
count
(
$condition
)
!=
1
||
!
isset
(
$condition
[
reset
(
static
::
primaryKey
())]))
{
throw
new
NotSupportedException
(
'UpdateAll is only supported by primary key in elasticsearch.'
);
}
if
(
isset
(
$attributes
[
reset
(
static
::
primaryKey
())]))
{
throw
new
NotSupportedException
(
'Updating the primary key is currently not supported by elasticsearch.'
);
}
$query
=
''
;
foreach
((
array
)
reset
(
$condition
)
as
$pk
)
{
if
(
is_array
(
$pk
))
{
$pk
=
reset
(
$pk
);
}
$action
=
Json
::
encode
(
array
(
"update"
=>
array
(
"_id"
=>
$pk
,
"_id"
=>
$pk
,
"_type"
=>
static
::
indexT
ype
(),
"_type"
=>
static
::
t
ype
(),
"_index"
=>
static
::
index
Name
(),
"_index"
=>
static
::
index
(),
)
,
]
,
)
);
]
);
$data
=
Json
::
encode
(
array
(
$data
=
Json
::
encode
(
array
(
"doc"
=>
$attributes
"doc"
=>
$attributes
));
));
$query
.=
$action
.
"
\n
"
.
$data
.
"
\n
"
;
$bulk
.=
$action
.
"
\n
"
.
$data
.
"
\n
"
;
// TODO implement pk change
}
}
$url
=
'/'
.
static
::
indexName
()
.
'/'
.
static
::
indexType
()
.
'/_bulk'
;
$response
=
static
::
getDb
()
->
http
()
->
post
(
$url
,
array
(),
$query
)
->
send
();
// TODO do this via command
$url
=
'/'
.
static
::
index
()
.
'/'
.
static
::
type
()
.
'/_bulk'
;
$response
=
static
::
getDb
()
->
http
()
->
post
(
$url
,
null
,
$bulk
)
->
send
();
$body
=
Json
::
decode
(
$response
->
getBody
(
true
));
$body
=
Json
::
decode
(
$response
->
getBody
(
true
));
$n
=
0
;
$n
=
0
;
foreach
(
$body
[
'items'
]
as
$item
)
{
foreach
(
$body
[
'items'
]
as
$item
)
{
if
(
$item
[
'update'
][
'ok'
])
{
if
(
$item
[
'update'
][
'ok'
])
{
$n
++
;
$n
++
;
}
}
// TODO might want to update the _version in update()
}
}
return
$n
;
return
$n
;
}
}
/**
* Updates the whole table using the provided counter changes and conditions.
* For example, to increment all customers' age by 1,
*
* ~~~
* Customer::updateAllCounters(array('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 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.
* @param array $params this parameter is ignored in redis implementation.
* @return integer the number of rows updated
*/
public
static
function
updateAllCounters
(
$counters
,
$condition
=
null
,
$params
=
array
())
{
throw
new
NotSupportedException
(
'Update Counters is not supported by elasticsearch.'
);
}
/**
/**
* Deletes rows in the table using the provided conditions.
* Deletes rows in the table using the provided conditions.
...
@@ -139,215 +258,63 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord
...
@@ -139,215 +258,63 @@ abstract class ActiveRecord extends \yii\db\ActiveRecord
* @param array $params this parameter is ignored in redis implementation.
* @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
=
array
()
)
public
static
function
deleteAll
(
$condition
=
null
,
$params
=
[]
)
{
{
// TODO use delete By Query feature
$bulk
=
''
;
// http://www.elasticsearch.org/guide/reference/api/delete-by-query/
foreach
((
array
)
$condition
as
$pk
)
{
if
(
count
(
$condition
)
!=
1
||
!
isset
(
$condition
[
reset
(
static
::
primaryKey
())]))
{
$bulk
=
Json
::
encode
([
throw
new
NotSupportedException
(
'DeleteAll is only supported by primary key in elasticsearch.'
);
"delete"
=>
[
}
$query
=
''
;
foreach
((
array
)
reset
(
$condition
)
as
$pk
)
{
if
(
is_array
(
$pk
))
{
$pk
=
reset
(
$pk
);
}
$query
.=
Json
::
encode
(
array
(
"delete"
=>
array
(
"_id"
=>
$pk
,
"_id"
=>
$pk
,
"_type"
=>
static
::
indexT
ype
(),
"_type"
=>
static
::
t
ype
(),
"_index"
=>
static
::
index
Name
(),
"_index"
=>
static
::
index
(),
)
,
]
,
)
)
.
"
\n
"
;
]
)
.
"
\n
"
;
}
}
$url
=
'/'
.
static
::
indexName
()
.
'/'
.
static
::
indexType
()
.
'/_bulk'
;
$response
=
static
::
getDb
()
->
http
()
->
post
(
$url
,
array
(),
$query
)
->
send
();
// TODO do this via command
$url
=
'/'
.
static
::
index
()
.
'/'
.
static
::
type
()
.
'/_bulk'
;
$response
=
static
::
getDb
()
->
http
()
->
post
(
$url
,
null
,
$bulk
)
->
send
();
$body
=
Json
::
decode
(
$response
->
getBody
(
true
));
$body
=
Json
::
decode
(
$response
->
getBody
(
true
));
$n
=
0
;
$n
=
0
;
foreach
(
$body
[
'items'
]
as
$item
)
{
foreach
(
$body
[
'items'
]
as
$item
)
{
if
(
$item
[
'delete'
][
'ok'
])
{
if
(
$item
[
'delete'
][
'ok'
])
{
$n
++
;
$n
++
;
}
}
// TODO might want to update the _version in update()
}
}
return
$n
;
return
$n
;
}
}
/**
/**
* Creates an [[ActiveQuery]] instance.
* @inheritdoc
* This method is called by [[find()]], [[findBySql()]] and [[count()]] to start a SELECT query.
* You may override this method to return a customized query (e.g. `CustomerQuery` specified
* written for querying `Customer` purpose.)
* @return ActiveQuery the newly created [[ActiveQuery]] instance.
*/
public
static
function
createQuery
()
{
return
new
ActiveQuery
(
array
(
'modelClass'
=>
get_called_class
(),
));
}
/**
* Declares the name of the database table associated with this AR class.
* @return string the table name
*/
*/
public
static
function
tableName
()
public
static
function
updateAllCounters
(
$counters
,
$condition
=
null
,
$params
=
[])
{
return
static
::
getTableSchema
()
->
name
;
}
public
static
function
primaryKey
()
{
return
array
(
'id'
);
}
public
static
function
columns
()
{
return
array
(
'id'
=>
'integer'
);
}
public
static
function
indexName
()
{
{
return
Inflector
::
pluralize
(
Inflector
::
camel2id
(
StringHelper
::
basename
(
get_called_class
()),
'-'
)
);
throw
new
NotSupportedException
(
'Update Counters is not supported by elasticsearch ActiveRecord.'
);
}
}
public
static
function
indexType
()
{
return
Inflector
::
camel2id
(
StringHelper
::
basename
(
get_called_class
()),
'-'
);
}
private
static
$_tables
;
/**
/**
* Returns the schema information of the DB table associated with this AR class.
* @inheritdoc
* @return TableSchema the schema information of the DB table associated with this AR class.
* @throws InvalidConfigException if the table for the AR class does not exist.
*/
*/
public
static
function
getTableSchema
()
public
static
function
getTableSchema
()
{
{
$class
=
get_called_class
();
throw
new
NotSupportedException
(
'getTableSchema() is not supported by elasticsearch ActiveRecord.'
);
if
(
isset
(
self
::
$_tables
[
$class
]))
{
return
self
::
$_tables
[
$class
];
}
return
self
::
$_tables
[
$class
]
=
new
TableSchema
(
array
(
'schemaName'
=>
static
::
indexName
(),
'name'
=>
static
::
indexType
(),
'primaryKey'
=>
static
::
primaryKey
(),
'columns'
=>
static
::
columns
(),
));
}
}
/**
/**
* Declares a `has-one` relation.
* @inheritDoc
* The declaration is returned in terms of an [[ActiveRelation]] instance
* through which the related record can be queried and retrieved back.
*
* A `has-one` relation means that there is at most one related record matching
* the criteria set by this relation, e.g., a customer has one country.
*
* For example, to declare the `country` relation for `Customer` class, we can write
* the following code in the `Customer` class:
*
* ~~~
* public function getCountry()
* {
* return $this->hasOne('Country', array('id' => 'country_id'));
* }
* ~~~
*
* Note that in the above, the 'id' key in the `$link` parameter refers to an attribute name
* in the related class `Country`, while the 'country_id' value refers to an attribute name
* in the current AR class.
*
* Call methods declared in [[ActiveRelation]] to further customize the relation.
*
* @param string $class the class name of the related record
* @param array $link the primary-foreign key constraint. The keys of the array refer to
* the columns in the table associated with the `$class` model, while the values of the
* array refer to the corresponding columns in the table associated with this AR class.
* @return ActiveRelation the relation object.
*/
*/
public
function
hasOne
(
$class
,
$link
)
public
static
function
tableName
(
)
{
{
return
new
ActiveRelation
(
array
(
return
static
::
index
()
.
'/'
.
static
::
type
();
'modelClass'
=>
$this
->
getNamespacedClass
(
$class
),
'primaryModel'
=>
$this
,
'link'
=>
$link
,
'multiple'
=>
false
,
));
}
}
/**
/**
* Declares a `has-many` relation.
* @inheritdoc
* The declaration is returned in terms of an [[ActiveRelation]] instance
* through which the related record can be queried and retrieved back.
*
* A `has-many` relation means that there are multiple related records matching
* the criteria set by this relation, e.g., a customer has many orders.
*
* For example, to declare the `orders` relation for `Customer` class, we can write
* the following code in the `Customer` class:
*
* ~~~
* public function getOrders()
* {
* return $this->hasMany('Order', array('customer_id' => 'id'));
* }
* ~~~
*
* Note that in the above, the 'customer_id' key in the `$link` parameter refers to
* an attribute name in the related class `Order`, while the 'id' value refers to
* an attribute name in the current AR class.
*
* @param string $class the class name of the related record
* @param array $link the primary-foreign key constraint. The keys of the array refer to
* the columns in the table associated with the `$class` model, while the values of the
* array refer to the corresponding columns in the table associated with this AR class.
* @return ActiveRelation the relation object.
*/
public
function
hasMany
(
$class
,
$link
)
{
return
new
ActiveRelation
(
array
(
'modelClass'
=>
$this
->
getNamespacedClass
(
$class
),
'primaryModel'
=>
$this
,
'link'
=>
$link
,
'multiple'
=>
true
,
));
}
/**
* @inheritDocs
*/
*/
public
function
insert
(
$runValidation
=
true
,
$attributes
=
null
)
public
static
function
findBySql
(
$sql
,
$params
=
[]
)
{
{
if
(
$runValidation
&&
!
$this
->
validate
(
$attributes
))
{
throw
new
NotSupportedException
(
'findBySql() is not supported by elasticsearch ActiveRecord.'
);
return
false
;
}
if
(
$this
->
beforeSave
(
true
))
{
$db
=
static
::
getDb
();
$values
=
$this
->
getDirtyAttributes
(
$attributes
);
$key
=
reset
(
$this
->
primaryKey
());
$pk
=
$this
->
getAttribute
(
$key
);
//unset($values[$key]);
// save attributes
if
(
$pk
===
null
)
{
$url
=
'/'
.
static
::
indexName
()
.
'/'
.
static
::
indexType
();
$request
=
$db
->
http
()
->
post
(
$url
,
array
(),
Json
::
encode
(
$values
));
}
else
{
$url
=
'/'
.
static
::
indexName
()
.
'/'
.
static
::
indexType
()
.
'/'
.
$pk
;
$request
=
$db
->
http
()
->
put
(
$url
,
array
(),
Json
::
encode
(
$values
));
}
$response
=
$request
->
send
();
$body
=
Json
::
decode
(
$response
->
getBody
(
true
));
if
(
!
$body
[
'ok'
])
{
return
false
;
}
$this
->
setOldAttributes
(
$values
);
if
(
$pk
===
null
)
{
$this
->
setAttribute
(
$key
,
$body
[
'_id'
]);
}
$this
->
afterSave
(
true
);
return
true
;
}
return
false
;
}
}
/**
/**
...
...
framework/yii/elasticsearch/Command.php
View file @
39ff11a3
...
@@ -7,6 +7,7 @@ namespace yii\elasticsearch;
...
@@ -7,6 +7,7 @@ namespace yii\elasticsearch;
use
yii\base\Component
;
use
yii\base\Component
;
use
yii\db\Exception
;
use
yii\helpers\Json
;
use
yii\helpers\Json
;
// camelCase vs. _
// camelCase vs. _
...
@@ -25,9 +26,6 @@ class Command extends Component
...
@@ -25,9 +26,6 @@ class Command extends Component
* @var Connection
* @var Connection
*/
*/
public
$db
;
public
$db
;
public
$api
=
'_search'
;
/**
/**
* @var string|array the indexes to execute the query on. Defaults to null meaning all indexes
* @var string|array the indexes to execute the query on. Defaults to null meaning all indexes
* @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search.html#search-multi-index
* @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search.html#search-multi-index
...
@@ -43,90 +41,35 @@ class Command extends Component
...
@@ -43,90 +41,35 @@ class Command extends Component
*/
*/
public
$query
;
public
$query
;
// private function createUrl($endPoint = null)
public
function
queryAll
(
$options
=
[])
// {
{
// if ($endPoint === null) {
$query
=
$this
->
query
;
// $endPoint = $this->api;
if
(
empty
(
$query
))
{
// }
$query
=
'{}'
;
// if ($this->index === null && $this->type === null) {
}
// return '/' . $endPoint;
if
(
is_array
(
$query
))
{
// }
$query
=
Json
::
encode
(
$query
);
// $index = $this->index;
}
// if ($index === null) {
$url
=
[
// $index = '_all';
$this
->
index
!==
null
?
$this
->
index
:
'_all'
,
// } elseif (is_array($index)) {
$this
->
type
!==
null
?
$this
->
type
:
'_all'
,
// $index = implode(',', $index);
'_search'
// }
];
// $type = $this->type;
$response
=
$this
->
db
->
http
()
->
post
(
$this
->
createUrl
(
$url
,
$options
),
null
,
$query
)
->
send
();
// if (is_array($type)) {
return
Json
::
decode
(
$response
->
getBody
(
true
))[
'hits'
];
// $type = implode(',', $type);
}
// }
// return '/' . $index . '/' . (empty($type) ? '' : $type . '/') . $endPoint;
public
function
queryOne
(
$options
=
[])
// }
{
//
$options
[
'size'
]
=
1
;
// public function queryAll()
return
$this
->
queryAll
(
$options
);
// {
}
// $query = $this->query;
// if (empty($query)) {
public
function
queryCount
(
$options
=
[])
// $query = '{}';
{
// }
$options
[
'search_type'
]
=
'count'
;
// if (is_array($query)) {
return
$this
->
queryAll
(
$options
);
// $query = Json::encode($query);
}
// }
// $http = $this->db->http();
// $response = $http->post($this->createUrl(), null, $query)->send();
// $data = Json::decode($response->getBody(true));
// // TODO store query meta data for later use
// $docs = array();
// switch ($this->api) {
// default:
// case '_search':
// if (isset($data['hits']['hits'])) {
// $docs = $data['hits']['hits'];
// }
// break;
// case '_mget':
// if (isset($data['docs'])) {
// $docs = $data['docs'];
// }
// break;
// }
// $rows = array();
// foreach($docs as $doc) {
// // TODO maybe return type info
// if (isset($doc['exists']) && !$doc['exists']) {
// continue;
// }
// $row = $doc['_source'];
// $row['id'] = $doc['_id'];
// $rows[] = $row;
// }
// return $rows;
// }
//
// public function queryOne()
// {
// // TODO set limit
// $rows = $this->queryAll();
// return reset($rows);
// }
//
// public function queryCount()
// {
// //http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-count.html
// $query = $this->query;
// if (empty($query)) {
// $query = '';
// }
// if (is_array($query)) {
// $query = Json::encode($query);
// }
// $http = $this->db->http();
// $response = $http->post($this->createUrl('_count'), null, $query)->send();
// $data = Json::decode($response->getBody(true));
// // TODO store query meta data for later use
// return $data['count'];
// }
/**
/**
...
@@ -161,8 +104,15 @@ class Command extends Component
...
@@ -161,8 +104,15 @@ class Command extends Component
*/
*/
public
function
get
(
$index
,
$type
,
$id
,
$options
=
[])
public
function
get
(
$index
,
$type
,
$id
,
$options
=
[])
{
{
$response
=
$this
->
db
->
http
()
->
post
(
$this
->
createUrl
([
$index
,
$type
,
$id
],
$options
))
->
send
();
$httpOptions
=
[
'exceptions'
=>
false
,
];
$response
=
$this
->
db
->
http
()
->
get
(
$this
->
createUrl
([
$index
,
$type
,
$id
],
$options
),
null
,
$httpOptions
)
->
send
();
if
(
$response
->
getStatusCode
()
==
200
||
$response
->
getStatusCode
()
==
404
)
{
return
Json
::
decode
(
$response
->
getBody
(
true
));
return
Json
::
decode
(
$response
->
getBody
(
true
));
}
else
{
throw
new
Exception
(
'Elasticsearch request failed.'
);
}
}
}
/**
/**
...
...
framework/yii/elasticsearch/Query.php
View file @
39ff11a3
<?php
<?php
/**
/**
* Created by JetBrains PhpStorm.
* @link http://www.yiiframework.com/
* User: cebe
* @copyright Copyright (c) 2008 Yii Software LLC
* Date: 30.09.13
* @license http://www.yiiframework.com/license/
* Time: 11:39
* To change this template use File | Settings | File Templates.
*/
*/
namespace
yii\elasticsearch
;
namespace
yii\elasticsearch
;
use
yii\base\Component
;
use
Yii
;
use
Yii
;
use
yii\base\Component
;
use
yii\db\QueryInterface
;
use
yii\db\QueryTrait
;
class
Query
extends
Component
/**
{
* Class Query
/**
*
* Sort ascending
* @author Carsten Brandt <mail@cebe.cc>
* @see orderBy
* @since 2.0
*/
const
SORT_ASC
=
false
;
/**
* Sort descending
* @see orderBy
*/
*/
const
SORT_DESC
=
true
;
class
Query
extends
Component
implements
QueryInterface
{
use
QueryTrait
;
/**
/**
* @var array the columns being selected. For example, `array('id', 'name')`.
* @var array the columns being selected. For example, `array('id', 'name')`.
* This is used to construct the SELECT clause in a SQL statement. If not set, if means selecting all columns.
* This is used to construct the SELECT clause in a SQL statement. If not set, if means selecting all columns.
* @see select()
* @see select()
*/
*/
public
$select
;
public
$select
;
// TODO fields
/**
* @var string|array query condition. This refers to the WHERE clause in a SQL statement.
public
$index
;
* For example, `age > 31 AND team = 1`.
* @see where()
*/
public
$where
;
/**
* @var integer maximum number of records to be returned. If not set or less than 0, it means no limit.
*/
public
$limit
;
/**
* @var integer zero-based offset from where the records are to be returned. If not set or
* less than 0, it means starting from the beginning.
*/
public
$offset
;
/**
* @var array how to sort the query results. This is used to construct the ORDER BY clause in a SQL statement.
* The array keys are the columns to be sorted by, and the array values are the corresponding sort directions which
* can be either [[Query::SORT_ASC]] or [[Query::SORT_DESC]]. The array may also contain [[Expression]] objects.
* If that is the case, the expressions will be converted into strings without any change.
*/
public
$orderBy
;
/**
* @var string|callable $column the name of the column by which the query results should be indexed by.
* This can also be a callable (e.g. anonymous function) that returns the index value based on the given
* row data. For more details, see [[indexBy()]]. This property is only used by [[all()]].
*/
public
$indexBy
;
public
$type
;
/**
/**
* Creates a DB command that can be used to execute this query.
* Creates a DB command that can be used to execute this query.
* @param Connection $db the database connection used to generate the SQL statement.
* @param Connection $db the database connection used to generate the SQL statement.
* If this parameter is not given, the `
db
` application component will be used.
* If this parameter is not given, the `
elasticsearch
` application component will be used.
* @return Command the created DB command instance.
* @return Command the created DB command instance.
*/
*/
public
function
createCommand
(
$db
=
null
)
public
function
createCommand
(
$db
=
null
)
{
{
if
(
$db
===
null
)
{
if
(
$db
===
null
)
{
$db
=
Yii
::
$app
->
elasticsearch
;
$db
=
Yii
::
$app
->
getComponent
(
'elasticsearch'
);
}
$query
=
$db
->
getQueryBuilder
()
->
build
(
$this
);
return
$db
->
createCommand
(
$query
);
}
}
/**
$query
=
$db
->
getQueryBuilder
()
->
build
(
$this
);
* Sets the [[indexBy]] property.
return
$db
->
createCommand
(
$query
,
$this
->
index
,
$this
->
type
);
* @param string|callable $column the name of the column by which the query results should be indexed by.
* This can also be a callable (e.g. anonymous function) that returns the index value based on the given
* row data. The signature of the callable should be:
*
* ~~~
* function ($row)
* {
* // return the index value corresponding to $row
* }
* ~~~
*
* @return Query the query object itself
*/
public
function
indexBy
(
$column
)
{
$this
->
indexBy
=
$column
;
return
$this
;
}
}
/**
/**
...
@@ -110,7 +61,7 @@ class Query extends Component
...
@@ -110,7 +61,7 @@ class Query extends Component
if
(
$this
->
indexBy
===
null
)
{
if
(
$this
->
indexBy
===
null
)
{
return
$rows
;
return
$rows
;
}
}
$result
=
array
()
;
$result
=
[]
;
foreach
(
$rows
as
$row
)
{
foreach
(
$rows
as
$row
)
{
if
(
is_string
(
$this
->
indexBy
))
{
if
(
is_string
(
$this
->
indexBy
))
{
$key
=
$row
[
$this
->
indexBy
];
$key
=
$row
[
$this
->
indexBy
];
...
@@ -137,291 +88,130 @@ class Query extends Component
...
@@ -137,291 +88,130 @@ class Query extends Component
/**
/**
* Returns the query result as a scalar value.
* Returns the query result as a scalar value.
* The value returned will be the first column in the first row of the query results.
* The value returned will be the first column in the first row of the query results.
* @param $column
* @param string $column name of the column to select
* @param Connection $db the database connection used to execute the query.
* If this parameter is not given, the `db` application component will be used.
* @return string|boolean the value of the first column in the first row of the query result.
* @return string|boolean the value of the first column in the first row of the query result.
* False is returned if the query result is empty.
* False is returned if the query result is empty.
*/
*/
public
function
scalar
(
$column
)
public
function
scalar
(
$column
,
$db
=
null
)
{
{
// TODO implement
$record
=
$this
->
one
(
$db
);
return
null
;
if
(
$record
===
null
)
{
return
false
;
}
else
{
return
$record
->
$column
;
}
}
}
// /**
// * Executes the query and returns the first column of the result.
// * @param Connection $db the database connection used to generate the SQL statement.
// * If this parameter is not given, the `db` application component will be used.
// * @return array the first column of the query result. An empty array is returned if the query results in nothing.
// */
// public function column($db = null)
// {
// return $this->createCommand($db)->queryColumn();
// }
/**
/**
*
Returns the number of records
.
*
Executes the query and returns the first column of the result
.
* @param Connection $db the database connection used to generate the SQL statement.
* @param Connection $db the database connection used to generate the SQL statement.
* If this parameter is not given, the `db` application component will be used.
* If this parameter is not given, the `db` application component will be used.
* @return
integer number of records
* @return
array the first column of the query result. An empty array is returned if the query results in nothing.
*/
*/
public
function
co
unt
(
$db
=
null
)
public
function
co
lumn
(
$db
=
null
)
{
{
return
$this
->
createCommand
(
$db
)
->
queryCo
unt
();
return
$this
->
createCommand
(
$db
)
->
queryCo
lumn
();
}
}
// /**
// * Returns the sum of the specified column values.
// * @param string $q the column name or expression.
// * Make sure you properly quote column names in the expression.
// * @param Connection $db the database connection used to generate the SQL statement.
// * If this parameter is not given, the `db` application component will be used.
// * @return integer the sum of the specified column values
// */
// public function sum($q, $db = null)
// {
// $this->select = array("SUM($q)");
// return $this->createCommand($db)->queryScalar();
// }
//
// /**
// * Returns the average of the specified column values.
// * @param string $q the column name or expression.
// * Make sure you properly quote column names in the expression.
// * @param Connection $db the database connection used to generate the SQL statement.
// * If this parameter is not given, the `db` application component will be used.
// * @return integer the average of the specified column values.
// */
// public function average($q, $db = null)
// {
// $this->select = array("AVG($q)");
// return $this->createCommand($db)->queryScalar();
// }
//
// /**
// * Returns the minimum of the specified column values.
// * @param string $q the column name or expression.
// * Make sure you properly quote column names in the expression.
// * @param Connection $db the database connection used to generate the SQL statement.
// * If this parameter is not given, the `db` application component will be used.
// * @return integer the minimum of the specified column values.
// */
// public function min($q, $db = null)
// {
// $this->select = array("MIN($q)");
// return $this->createCommand($db)->queryScalar();
// }
//
// /**
// * Returns the maximum of the specified column values.
// * @param string $q the column name or expression.
// * Make sure you properly quote column names in the expression.
// * @param Connection $db the database connection used to generate the SQL statement.
// * If this parameter is not given, the `db` application component will be used.
// * @return integer the maximum of the specified column values.
// */
// public function max($q, $db = null)
// {
// $this->select = array("MAX($q)");
// return $this->createCommand($db)->queryScalar();
// }
/**
/**
* Returns a value indicating whether the query result contains any row of data.
* Returns the number of records.
* @param string $q the COUNT expression. Defaults to '*'.
* Make sure you properly quote column names in the expression.
* @param Connection $db the database connection used to generate the SQL statement.
* @param Connection $db the database connection used to generate the SQL statement.
* If this parameter is not given, the `db` application component will be used.
* If this parameter is not given
(or null)
, the `db` application component will be used.
* @return
boolean whether the query result contains any row of data.
* @return
integer number of records
*/
*/
public
function
exists
(
)
public
function
count
(
$q
=
'*'
,
$db
=
null
)
{
{
return
$this
->
one
()
!==
null
;
$this
->
select
=
[
"COUNT(
$q
)"
];
return
$this
->
createCommand
(
$db
)
->
queryScalar
();
}
}
/**
/**
* Sets the WHERE part of the query.
* Returns the sum of the specified column values.
*
* @param string $q the column name or expression.
* The method requires a $condition parameter, and optionally a $params parameter
* Make sure you properly quote column names in the expression.
* specifying the values to be bound to the query.
* @param Connection $db the database connection used to generate the SQL statement.
*
* If this parameter is not given, the `db` application component will be used.
* The $condition parameter should be either a string (e.g. 'id=1') or an array.
* @return integer the sum of the specified column values
* If the latter, it must be in one of the following two formats:
*
* - hash format: `array('column1' => value1, 'column2' => value2, ...)`
* - operator format: `array(operator, operand1, operand2, ...)`
*
* A condition in hash format represents the following SQL expression in general:
* `column1=value1 AND column2=value2 AND ...`. In case when a value is an array,
* an `IN` expression will be generated. And if a value is null, `IS NULL` will be used
* in the generated expression. Below are some examples:
*
* - `array('type' => 1, 'status' => 2)` generates `(type = 1) AND (status = 2)`.
* - `array('id' => array(1, 2, 3), 'status' => 2)` generates `(id IN (1, 2, 3)) AND (status = 2)`.
* - `array('status' => null) generates `status IS NULL`.
*
* A condition in operator format generates the SQL expression according to the specified operator, which
* can be one of the followings:
*
* - `and`: the operands should be concatenated together using `AND`. For example,
* `array('and', 'id=1', 'id=2')` will generate `id=1 AND id=2`. If an operand is an array,
* it will be converted into a string using the rules described here. For example,
* `array('and', 'type=1', array('or', 'id=1', 'id=2'))` will generate `type=1 AND (id=1 OR id=2)`.
* The method will NOT do any quoting or escaping.
*
* - `or`: similar to the `and` operator except that the operands are concatenated using `OR`.
*
* - `between`: operand 1 should be the column name, and operand 2 and 3 should be the
* starting and ending values of the range that the column is in.
* For example, `array('between', 'id', 1, 10)` will generate `id BETWEEN 1 AND 10`.
*
* - `not between`: similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN`
* in the generated condition.
*
* - `in`: operand 1 should be a column or DB expression, and operand 2 be an array representing
* the range of the values that the column or DB expression should be in. For example,
* `array('in', 'id', array(1, 2, 3))` will generate `id IN (1, 2, 3)`.
* The method will properly quote the column name and escape values in the range.
*
* - `not in`: similar to the `in` operator except that `IN` is replaced with `NOT IN` in the generated condition.
*
* - `like`: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing
* the values that the column or DB expression should be like.
* For example, `array('like', 'name', '%tester%')` will generate `name LIKE '%tester%'`.
* When the value range is given as an array, multiple `LIKE` predicates will be generated and concatenated
* using `AND`. For example, `array('like', 'name', array('%test%', '%sample%'))` will generate
* `name LIKE '%test%' AND name LIKE '%sample%'`.
* The method will properly quote the column name and escape values in the range.
*
* - `or like`: similar to the `like` operator except that `OR` is used to concatenate the `LIKE`
* predicates when operand 2 is an array.
*
* - `not like`: similar to the `like` operator except that `LIKE` is replaced with `NOT LIKE`
* in the generated condition.
*
* - `or not like`: similar to the `not like` operator except that `OR` is used to concatenate
* the `NOT LIKE` predicates.
*
* @param string|array $condition the conditions that should be put in the WHERE part.
* @return Query the query object itself
* @see andWhere()
* @see orWhere()
*/
*/
public
function
where
(
$condition
)
public
function
sum
(
$q
,
$db
=
null
)
{
{
$this
->
where
=
$condition
;
$this
->
select
=
[
"SUM(
$q
)"
]
;
return
$this
;
return
$this
->
createCommand
(
$db
)
->
queryScalar
()
;
}
}
/**
/**
* Adds an additional WHERE condition to the existing one.
* Returns the average of the specified column values.
* The new condition and the existing one will be joined using the 'AND' operator.
* @param string $q the column name or expression.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* Make sure you properly quote column names in the expression.
* on how to specify this parameter.
* @param Connection $db the database connection used to generate the SQL statement.
* @return Query the query object itself
* If this parameter is not given, the `db` application component will be used.
* @see where()
* @return integer the average of the specified column values.
* @see orWhere()
*/
*/
public
function
a
ndWhere
(
$condition
)
public
function
a
verage
(
$q
,
$db
=
null
)
{
{
if
(
$this
->
where
===
null
)
{
$this
->
select
=
[
"AVG(
$q
)"
];
$this
->
where
=
$condition
;
return
$this
->
createCommand
(
$db
)
->
queryScalar
();
}
else
{
$this
->
where
=
array
(
'and'
,
$this
->
where
,
$condition
);
}
return
$this
;
}
}
/**
/**
* Adds an additional WHERE condition to the existing one.
* Returns the minimum of the specified column values.
* The new condition and the existing one will be joined using the 'OR' operator.
* @param string $q the column name or expression.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* Make sure you properly quote column names in the expression.
* on how to specify this parameter.
* @param Connection $db the database connection used to generate the SQL statement.
* @return Query the query object itself
* If this parameter is not given, the `db` application component will be used.
* @see where()
* @return integer the minimum of the specified column values.
* @see andWhere()
*/
*/
public
function
orWhere
(
$condition
)
public
function
min
(
$q
,
$db
=
null
)
{
{
if
(
$this
->
where
===
null
)
{
$this
->
select
=
[
"MIN(
$q
)"
];
$this
->
where
=
$condition
;
return
$this
->
createCommand
(
$db
)
->
queryScalar
();
}
else
{
$this
->
where
=
array
(
'or'
,
$this
->
where
,
$condition
);
}
return
$this
;
}
}
/**
/**
* Sets the ORDER BY part of the query.
* Returns the maximum of the specified column values.
* @param string|array $columns the columns (and the directions) to be ordered by.
* @param string $q the column name or expression.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array
* Make sure you properly quote column names in the expression.
* (e.g. `array('id' => Query::SORT_ASC, 'name' => Query::SORT_DESC)`).
* @param Connection $db the database connection used to generate the SQL statement.
* The method will automatically quote the column names unless a column contains some parenthesis
* If this parameter is not given, the `db` application component will be used.
* (which means the column contains a DB expression).
* @return integer the maximum of the specified column values.
* @return Query the query object itself
* @see addOrderBy()
*/
*/
public
function
orderBy
(
$columns
)
public
function
max
(
$q
,
$db
=
null
)
{
{
$this
->
orderBy
=
$this
->
normalizeOrderBy
(
$columns
)
;
$this
->
select
=
[
"MAX(
$q
)"
]
;
return
$this
;
return
$this
->
createCommand
(
$db
)
->
queryScalar
()
;
}
}
/**
/**
* Adds additional ORDER BY columns to the query.
* Returns a value indicating whether the query result contains any row of data.
* @param string|array $columns the columns (and the directions) to be ordered by.
* @param Connection $db the database connection used to execute the query.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array
* If this parameter is not given, the `db` application component will be used.
* (e.g. `array('id' => Query::SORT_ASC, 'name' => Query::SORT_DESC)`).
* @return boolean whether the query result contains any row of data.
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return Query the query object itself
* @see orderBy()
*/
*/
public
function
addOrderBy
(
$columns
)
public
function
exists
(
$db
=
null
)
{
$columns
=
$this
->
normalizeOrderBy
(
$columns
);
if
(
$this
->
orderBy
===
null
)
{
$this
->
orderBy
=
$columns
;
}
else
{
$this
->
orderBy
=
array_merge
(
$this
->
orderBy
,
$columns
);
}
return
$this
;
}
protected
function
normalizeOrderBy
(
$columns
)
{
{
if
(
is_array
(
$columns
))
{
// TODO check for exists
return
$columns
;
return
$this
->
one
(
$db
)
!==
null
;
}
else
{
$columns
=
preg_split
(
'/\s*,\s*/'
,
trim
(
$columns
),
-
1
,
PREG_SPLIT_NO_EMPTY
);
$result
=
array
();
foreach
(
$columns
as
$column
)
{
if
(
preg_match
(
'/^(.*?)\s+(asc|desc)$/i'
,
$column
,
$matches
))
{
$result
[
$matches
[
1
]]
=
strcasecmp
(
$matches
[
2
],
'desc'
)
?
self
::
SORT_ASC
:
self
::
SORT_DESC
;
}
else
{
$result
[
$column
]
=
self
::
SORT_ASC
;
}
}
return
$result
;
}
}
}
/**
/**
* Sets the LIMIT part of the query.
* Executes the query and returns all results as an array.
* @param integer $limit the limit. Use null or negative value to disable limit.
* @param Connection $db the database connection used to execute the query.
* @return Query the query object itself
* If this parameter is not given, the `elasticsearch` application component will be used.
* @return array the query results. If the query results in nothing, an empty array will be returned.
*/
*/
public
function
limit
(
$limit
)
public
function
delete
(
$db
=
null
)
{
{
$this
->
limit
=
$limit
;
// TODO http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-delete-by-query.html
return
$this
;
}
}
/**
public
function
from
(
$index
,
$type
=
null
)
* Sets the OFFSET part of the query.
* @param integer $offset the offset. Use null or negative value to disable offset.
* @return Query the query object itself
*/
public
function
offset
(
$offset
)
{
{
$this
->
offset
=
$offset
;
$this
->
index
=
$index
;
return
$this
;
$this
->
type
=
$type
;
}
}
}
}
\ No newline at end of file
framework/yii/redis/ActiveRecord.php
View file @
39ff11a3
...
@@ -298,7 +298,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
...
@@ -298,7 +298,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
*/
*/
public
static
function
getTableSchema
()
public
static
function
getTableSchema
()
{
{
throw
new
NotSupportedException
(
'getTableSchema() is not supported by redis ActiveRecord'
);
throw
new
NotSupportedException
(
'getTableSchema() is not supported by redis ActiveRecord
.
'
);
}
}
/**
/**
...
@@ -306,7 +306,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
...
@@ -306,7 +306,7 @@ class ActiveRecord extends \yii\db\ActiveRecord
*/
*/
public
static
function
findBySql
(
$sql
,
$params
=
[])
public
static
function
findBySql
(
$sql
,
$params
=
[])
{
{
throw
new
NotSupportedException
(
'findBySql() is not supported by redis ActiveRecord'
);
throw
new
NotSupportedException
(
'findBySql() is not supported by redis ActiveRecord
.
'
);
}
}
/**
/**
...
...
tests/unit/data/ar/elasticsearch/Customer.php
View file @
39ff11a3
...
@@ -17,15 +17,9 @@ class Customer extends ActiveRecord
...
@@ -17,15 +17,9 @@ class Customer extends ActiveRecord
public
$status2
;
public
$status2
;
public
static
function
column
s
()
public
static
function
attribute
s
()
{
{
return
array
(
return
[
'name'
,
'email'
,
'address'
,
'status'
];
'id'
=>
'integer'
,
'name'
=>
'string'
,
'email'
=>
'string'
,
'address'
=>
'string'
,
'status'
=>
'integer'
,
);
}
}
public
function
getOrders
()
public
function
getOrders
()
...
...
tests/unit/data/ar/elasticsearch/Item.php
View file @
39ff11a3
...
@@ -11,12 +11,8 @@ namespace yiiunit\data\ar\elasticsearch;
...
@@ -11,12 +11,8 @@ namespace yiiunit\data\ar\elasticsearch;
*/
*/
class
Item
extends
ActiveRecord
class
Item
extends
ActiveRecord
{
{
public
static
function
column
s
()
public
static
function
attribute
s
()
{
{
return
array
(
return
[
'name'
,
'category_id'
];
'id'
=>
'integer'
,
'name'
=>
'string'
,
'category_id'
=>
'integer'
,
);
}
}
}
}
tests/unit/data/ar/elasticsearch/Order.php
View file @
39ff11a3
...
@@ -12,29 +12,24 @@ namespace yiiunit\data\ar\elasticsearch;
...
@@ -12,29 +12,24 @@ namespace yiiunit\data\ar\elasticsearch;
*/
*/
class
Order
extends
ActiveRecord
class
Order
extends
ActiveRecord
{
{
public
static
function
column
s
()
public
static
function
attribute
s
()
{
{
return
array
(
return
[
'customer_id'
,
'create_time'
,
'total'
];
'id'
=>
'integer'
,
'customer_id'
=>
'integer'
,
'create_time'
=>
'integer'
,
'total'
=>
'integer'
,
);
}
}
public
function
getCustomer
()
public
function
getCustomer
()
{
{
return
$this
->
hasOne
(
'Customer'
,
array
(
'id'
=>
'customer_id'
)
);
return
$this
->
hasOne
(
'Customer'
,
[
'id'
=>
'customer_id'
]
);
}
}
public
function
getOrderItems
()
public
function
getOrderItems
()
{
{
return
$this
->
hasMany
(
'OrderItem'
,
array
(
'order_id'
=>
'id'
)
);
return
$this
->
hasMany
(
'OrderItem'
,
[
'order_id'
=>
'id'
]
);
}
}
public
function
getItems
()
public
function
getItems
()
{
{
return
$this
->
hasMany
(
'Item'
,
array
(
'id'
=>
'item_id'
)
)
return
$this
->
hasMany
(
'Item'
,
[
'id'
=>
'item_id'
]
)
->
via
(
'orderItems'
,
function
(
$q
)
{
->
via
(
'orderItems'
,
function
(
$q
)
{
// additional query configuration
// additional query configuration
})
->
orderBy
(
'id'
);
})
->
orderBy
(
'id'
);
...
@@ -42,9 +37,9 @@ class Order extends ActiveRecord
...
@@ -42,9 +37,9 @@ class Order extends ActiveRecord
public
function
getBooks
()
public
function
getBooks
()
{
{
return
$this
->
hasMany
(
'Item'
,
array
(
'id'
=>
'item_id'
)
)
return
$this
->
hasMany
(
'Item'
,
[
'id'
=>
'item_id'
]
)
->
viaTable
(
'tbl_order_item'
,
array
(
'order_id'
=>
'id'
)
)
->
viaTable
(
'tbl_order_item'
,
[
'order_id'
=>
'id'
]
)
->
where
(
array
(
'category_id'
=>
1
)
);
->
where
(
[
'category_id'
=>
1
]
);
}
}
public
function
beforeSave
(
$insert
)
public
function
beforeSave
(
$insert
)
...
...
tests/unit/data/ar/elasticsearch/OrderItem.php
View file @
39ff11a3
...
@@ -12,23 +12,18 @@ namespace yiiunit\data\ar\elasticsearch;
...
@@ -12,23 +12,18 @@ namespace yiiunit\data\ar\elasticsearch;
*/
*/
class
OrderItem
extends
ActiveRecord
class
OrderItem
extends
ActiveRecord
{
{
public
static
function
column
s
()
public
static
function
attribute
s
()
{
{
return
array
(
return
[
'order_id'
,
'item_id'
,
'quantity'
,
'subtotal'
];
'order_id'
=>
'integer'
,
'item_id'
=>
'integer'
,
'quantity'
=>
'integer'
,
'subtotal'
=>
'integer'
,
);
}
}
public
function
getOrder
()
public
function
getOrder
()
{
{
return
$this
->
hasOne
(
'Order'
,
array
(
'id'
=>
'order_id'
)
);
return
$this
->
hasOne
(
'Order'
,
[
'id'
=>
'order_id'
]
);
}
}
public
function
getItem
()
public
function
getItem
()
{
{
return
$this
->
hasOne
(
'Item'
,
array
(
'id'
=>
'item_id'
)
);
return
$this
->
hasOne
(
'Item'
,
[
'id'
=>
'item_id'
]
);
}
}
}
}
tests/unit/framework/elasticsearch/ActiveRecordTest.php
View file @
39ff11a3
...
@@ -2,7 +2,6 @@
...
@@ -2,7 +2,6 @@
namespace
yiiunit\framework\elasticsearch
;
namespace
yiiunit\framework\elasticsearch
;
use
yii\db\Query
;
use
yii\elasticsearch\Connection
;
use
yii\elasticsearch\Connection
;
use
yii\elasticsearch\ActiveQuery
;
use
yii\elasticsearch\ActiveQuery
;
use
yii\helpers\Json
;
use
yii\helpers\Json
;
...
@@ -25,42 +24,53 @@ class ActiveRecordTest extends ElasticSearchTestCase
...
@@ -25,42 +24,53 @@ class ActiveRecordTest extends ElasticSearchTestCase
$db
->
http
()
->
delete
(
'_all'
)
->
send
();
$db
->
http
()
->
delete
(
'_all'
)
->
send
();
$customer
=
new
Customer
();
$customer
=
new
Customer
();
$customer
->
setAttributes
(
array
(
'id'
=>
1
,
'email'
=>
'user1@example.com'
,
'name'
=>
'user1'
,
'address'
=>
'address1'
,
'status'
=>
1
),
false
);
$customer
->
primaryKey
=
1
;
$customer
->
setAttributes
(
array
(
'email'
=>
'user1@example.com'
,
'name'
=>
'user1'
,
'address'
=>
'address1'
,
'status'
=>
1
),
false
);
$customer
->
save
(
false
);
$customer
->
save
(
false
);
$customer
=
new
Customer
();
$customer
=
new
Customer
();
$customer
->
setAttributes
(
array
(
'id'
=>
2
,
'email'
=>
'user2@example.com'
,
'name'
=>
'user2'
,
'address'
=>
'address2'
,
'status'
=>
1
),
false
);
$customer
->
primaryKey
=
2
;
$customer
->
setAttributes
(
array
(
'email'
=>
'user2@example.com'
,
'name'
=>
'user2'
,
'address'
=>
'address2'
,
'status'
=>
1
),
false
);
$customer
->
save
(
false
);
$customer
->
save
(
false
);
$customer
=
new
Customer
();
$customer
=
new
Customer
();
$customer
->
setAttributes
(
array
(
'id'
=>
3
,
'email'
=>
'user3@example.com'
,
'name'
=>
'user3'
,
'address'
=>
'address3'
,
'status'
=>
2
),
false
);
$customer
->
primaryKey
=
3
;
$customer
->
setAttributes
(
array
(
'email'
=>
'user3@example.com'
,
'name'
=>
'user3'
,
'address'
=>
'address3'
,
'status'
=>
2
),
false
);
$customer
->
save
(
false
);
$customer
->
save
(
false
);
// INSERT INTO tbl_category (name) VALUES ('Books');
// INSERT INTO tbl_category (name) VALUES ('Books');
// INSERT INTO tbl_category (name) VALUES ('Movies');
// INSERT INTO tbl_category (name) VALUES ('Movies');
$item
=
new
Item
();
$item
=
new
Item
();
$item
->
setAttributes
(
array
(
'id'
=>
1
,
'name'
=>
'Agile Web Application Development with Yii1.1 and PHP5'
,
'category_id'
=>
1
),
false
);
$item
->
primaryKey
=
1
;
$item
->
setAttributes
(
array
(
'name'
=>
'Agile Web Application Development with Yii1.1 and PHP5'
,
'category_id'
=>
1
),
false
);
$item
->
save
(
false
);
$item
->
save
(
false
);
$item
=
new
Item
();
$item
=
new
Item
();
$item
->
setAttributes
(
array
(
'id'
=>
2
,
'name'
=>
'Yii 1.1 Application Development Cookbook'
,
'category_id'
=>
1
),
false
);
$item
->
primaryKey
=
2
;
$item
->
setAttributes
(
array
(
'name'
=>
'Yii 1.1 Application Development Cookbook'
,
'category_id'
=>
1
),
false
);
$item
->
save
(
false
);
$item
->
save
(
false
);
$item
=
new
Item
();
$item
=
new
Item
();
$item
->
setAttributes
(
array
(
'id'
=>
3
,
'name'
=>
'Ice Age'
,
'category_id'
=>
2
),
false
);
$item
->
primaryKey
=
3
;
$item
->
setAttributes
(
array
(
'name'
=>
'Ice Age'
,
'category_id'
=>
2
),
false
);
$item
->
save
(
false
);
$item
->
save
(
false
);
$item
=
new
Item
();
$item
=
new
Item
();
$item
->
setAttributes
(
array
(
'id'
=>
4
,
'name'
=>
'Toy Story'
,
'category_id'
=>
2
),
false
);
$item
->
primaryKey
=
4
;
$item
->
setAttributes
(
array
(
'name'
=>
'Toy Story'
,
'category_id'
=>
2
),
false
);
$item
->
save
(
false
);
$item
->
save
(
false
);
$item
=
new
Item
();
$item
=
new
Item
();
$item
->
setAttributes
(
array
(
'id'
=>
5
,
'name'
=>
'Cars'
,
'category_id'
=>
2
),
false
);
$item
->
primaryKey
=
5
;
$item
->
setAttributes
(
array
(
'name'
=>
'Cars'
,
'category_id'
=>
2
),
false
);
$item
->
save
(
false
);
$item
->
save
(
false
);
$order
=
new
Order
();
$order
=
new
Order
();
$order
->
setAttributes
(
array
(
'id'
=>
1
,
'customer_id'
=>
1
,
'create_time'
=>
1325282384
,
'total'
=>
110.0
),
false
);
$order
->
primaryKey
=
1
;
$order
->
setAttributes
(
array
(
'customer_id'
=>
1
,
'create_time'
=>
1325282384
,
'total'
=>
110.0
),
false
);
$order
->
save
(
false
);
$order
->
save
(
false
);
$order
=
new
Order
();
$order
=
new
Order
();
$order
->
setAttributes
(
array
(
'id'
=>
2
,
'customer_id'
=>
2
,
'create_time'
=>
1325334482
,
'total'
=>
33.0
),
false
);
$order
->
primaryKey
=
2
;
$order
->
setAttributes
(
array
(
'customer_id'
=>
2
,
'create_time'
=>
1325334482
,
'total'
=>
33.0
),
false
);
$order
->
save
(
false
);
$order
->
save
(
false
);
$order
=
new
Order
();
$order
=
new
Order
();
$order
->
setAttributes
(
array
(
'id'
=>
3
,
'customer_id'
=>
2
,
'create_time'
=>
1325502201
,
'total'
=>
40.0
),
false
);
$order
->
primaryKey
=
3
;
$order
->
setAttributes
(
array
(
'customer_id'
=>
2
,
'create_time'
=>
1325502201
,
'total'
=>
40.0
),
false
);
$order
->
save
(
false
);
$order
->
save
(
false
);
// $orderItem = new OrderItem();
// $orderItem = new OrderItem();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment