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
9da7a80f
Commit
9da7a80f
authored
Nov 28, 2013
by
Paul Klimov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Mongo query condition composition composed.
parent
1a31b238
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
326 additions
and
21 deletions
+326
-21
Collection.php
extensions/mongo/Collection.php
+78
-12
Query.php
extensions/mongo/Query.php
+55
-9
QueryRunTest.php
tests/unit/extensions/mongo/QueryRunTest.php
+111
-0
QueryTest.php
tests/unit/extensions/mongo/QueryTest.php
+82
-0
No files found.
extensions/mongo/Collection.php
View file @
9da7a80f
...
...
@@ -7,6 +7,7 @@
namespace
yii\mongo
;
use
yii\base\InvalidParamException
;
use
yii\base\Object
;
use
Yii
;
...
...
@@ -32,23 +33,23 @@ class Collection extends Object
}
/**
* @param array $
query
* @param array $
condition
* @param array $fields
* @return \MongoCursor
*/
public
function
find
(
$
query
=
[],
$fields
=
[])
public
function
find
(
$
condition
=
[],
$fields
=
[])
{
return
$this
->
mongoCollection
->
find
(
$
query
,
$fields
);
return
$this
->
mongoCollection
->
find
(
$
this
->
buildCondition
(
$condition
)
,
$fields
);
}
/**
* @param array $
query
* @param array $
condition
* @param array $fields
* @return array
*/
public
function
findAll
(
$
query
=
[],
$fields
=
[])
public
function
findAll
(
$
condition
=
[],
$fields
=
[])
{
$cursor
=
$this
->
find
(
$
query
,
$fields
);
$cursor
=
$this
->
find
(
$
condition
,
$fields
);
$result
=
[];
foreach
(
$cursor
as
$data
)
{
$result
[]
=
$data
;
...
...
@@ -102,19 +103,19 @@ class Collection extends Object
/**
* Updates the rows, which matches given criteria by given data.
* @param array $c
riteria
description of the objects to update.
* @param array $c
ondition
description of the objects to update.
* @param array $newData the object with which to update the matching records.
* @param array $options list of options in format: optionName => optionValue.
* @return boolean whether operation was successful.
* @throws Exception on failure.
*/
public
function
update
(
$c
riteria
,
$newData
,
$options
=
[])
public
function
update
(
$c
ondition
,
$newData
,
$options
=
[])
{
$token
=
'Updating data in '
.
$this
->
mongoCollection
->
getName
();
Yii
::
info
(
$token
,
__METHOD__
);
try
{
Yii
::
beginProfile
(
$token
,
__METHOD__
);
$this
->
mongoCollection
->
update
(
$
criteria
,
$newData
,
$options
);
$this
->
mongoCollection
->
update
(
$
this
->
buildCondition
(
$condition
)
,
$newData
,
$options
);
Yii
::
endProfile
(
$token
,
__METHOD__
);
return
true
;
}
catch
(
\Exception
$e
)
{
...
...
@@ -147,18 +148,18 @@ class Collection extends Object
/**
* Removes data from the collection.
* @param array $c
riteria
description of records to remove.
* @param array $c
ondition
description of records to remove.
* @param array $options list of options in format: optionName => optionValue.
* @return boolean whether operation was successful.
* @throws Exception on failure.
*/
public
function
remove
(
$c
riteria
=
[],
$options
=
[])
public
function
remove
(
$c
ondition
=
[],
$options
=
[])
{
$token
=
'Removing data from '
.
$this
->
mongoCollection
->
getName
();
Yii
::
info
(
$token
,
__METHOD__
);
try
{
Yii
::
beginProfile
(
$token
,
__METHOD__
);
$this
->
tryResultError
(
$this
->
mongoCollection
->
remove
(
$
criteria
,
$options
));
$this
->
tryResultError
(
$this
->
mongoCollection
->
remove
(
$
this
->
buildCondition
(
$condition
)
,
$options
));
Yii
::
endProfile
(
$token
,
__METHOD__
);
return
true
;
}
catch
(
\Exception
$e
)
{
...
...
@@ -182,4 +183,68 @@ class Collection extends Object
throw
new
Exception
(
'Unknown error, use "w=1" option to enable error tracking'
);
}
}
/**
* Converts user friendly condition keyword into actual Mongo condition keyword.
* @param string $key raw condition key.
* @return string actual key.
*/
protected
function
normalizeConditionKeyword
(
$key
)
{
static
$map
=
[
'or'
=>
'$or'
,
'>'
=>
'$gt'
,
'>='
=>
'$gte'
,
'<'
=>
'$lt'
,
'<='
=>
'$lte'
,
'!='
=>
'$ne'
,
'<>'
=>
'$ne'
,
'in'
=>
'$in'
,
'not in'
=>
'$nin'
,
'all'
=>
'$all'
,
'size'
=>
'$size'
,
'type'
=>
'$type'
,
'exists'
=>
'$exists'
,
'notexists'
=>
'$exists'
,
'elemmatch'
=>
'$elemMatch'
,
'mod'
=>
'$mod'
,
'%'
=>
'$mod'
,
'='
=>
'$$eq'
,
'=='
=>
'$$eq'
,
'where'
=>
'$where'
];
$key
=
strtolower
(
$key
);
if
(
array_key_exists
(
$key
,
$map
))
{
return
$map
[
$key
];
}
else
{
return
$key
;
}
}
/**
* Builds up Mongo condition from user friendly condition.
* @param array $condition raw condition.
* @return array normalized Mongo condition.
* @throws \yii\base\InvalidParamException on invalid condition given.
*/
public
function
buildCondition
(
$condition
)
{
if
(
!
is_array
(
$condition
))
{
throw
new
InvalidParamException
(
'Condition should be an array.'
);
}
$result
=
[];
foreach
(
$condition
as
$key
=>
$value
)
{
if
(
is_array
(
$value
))
{
$actualValue
=
$this
->
buildCondition
(
$value
);
}
else
{
$actualValue
=
$value
;
}
if
(
is_numeric
(
$key
))
{
$result
[]
=
$actualValue
;
}
else
{
$result
[
$this
->
normalizeConditionKeyword
(
$key
)]
=
$actualValue
;
}
}
return
$result
;
}
}
\ No newline at end of file
extensions/mongo/Query.php
View file @
9da7a80f
...
...
@@ -74,26 +74,72 @@ class Query extends Component implements QueryInterface
}
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'AND' operator.
* @param array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @return static the query object itself
* @see where()
* @see orWhere()
*/
public
function
andWhere
(
$condition
)
{
if
(
is_array
(
$this
->
where
))
{
$this
->
where
=
array_merge
(
$this
->
where
,
$condition
);
}
else
{
$this
->
where
=
$condition
;
}
return
$this
;
}
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'OR' operator.
* @param array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @return static the query object itself
* @see where()
* @see andWhere()
*/
public
function
orWhere
(
$condition
)
{
if
(
is_array
(
$this
->
where
))
{
if
(
array_key_exists
(
'or'
,
$this
->
where
)
&&
count
(
$this
->
where
)
==
1
)
{
$this
->
where
[
'or'
][]
=
$condition
;
}
else
{
$this
->
where
=
[
'or'
=>
[
$this
->
where
,
$condition
]
];
}
}
else
{
$this
->
where
=
$condition
;
}
return
$this
;
}
/**
* @param Connection $db the database connection used to execute the query.
* @return \MongoCursor mongo cursor instance.
*/
protected
function
buildCursor
(
$db
=
null
)
{
// TODO: compose query
$query
=
[];
$where
=
$this
->
where
;
if
(
!
is_array
(
$where
))
{
$where
=
[];
}
$selectFields
=
[];
if
(
!
empty
(
$this
->
select
))
{
foreach
(
$this
->
select
as
$fieldName
)
{
$selectFields
[
$fieldName
]
=
true
;
}
}
$cursor
=
$this
->
getCollection
(
$db
)
->
find
(
$
query
,
$selectFields
);
$cursor
=
$this
->
getCollection
(
$db
)
->
find
(
$
where
,
$selectFields
);
if
(
!
empty
(
$this
->
orderBy
))
{
$sort
=
[];
foreach
(
$this
->
orderBy
as
$fieldName
=>
$sortOrder
)
{
$sort
[
$fieldName
]
=
$sortOrder
===
SORT_DESC
?
\MongoCollection
::
DESCENDING
:
\MongoCollection
::
ASCENDING
;
}
$cursor
->
sort
(
$
this
->
orderBy
);
$cursor
->
sort
(
$
sort
);
}
$cursor
->
limit
(
$this
->
limit
);
$cursor
->
skip
(
$this
->
offset
);
...
...
@@ -109,17 +155,17 @@ class Query extends Component implements QueryInterface
public
function
all
(
$db
=
null
)
{
$cursor
=
$this
->
buildCursor
(
$db
);
if
(
$this
->
indexBy
===
null
)
{
return
iterator_to_array
(
$cursor
);
}
else
{
$result
=
[];
foreach
(
$cursor
as
$row
)
{
$result
=
[];
foreach
(
$cursor
as
$row
)
{
if
(
$this
->
indexBy
!==
null
)
{
if
(
is_string
(
$this
->
indexBy
))
{
$key
=
$row
[
$this
->
indexBy
];
}
else
{
$key
=
call_user_func
(
$this
->
indexBy
,
$row
);
}
$result
[
$key
]
=
$row
;
}
else
{
$result
[]
=
$row
;
}
}
return
$result
;
...
...
tests/unit/extensions/mongo/QueryRunTest.php
0 → 100644
View file @
9da7a80f
<?php
namespace
yiiunit\extensions\mongo
;
use
yii\mongo\Query
;
/**
* @group mongo
*/
class
QueryRunTest
extends
MongoTestCase
{
protected
function
setUp
()
{
parent
::
setUp
();
$this
->
setUpTestRows
();
}
protected
function
tearDown
()
{
$this
->
dropCollection
(
'customer'
);
parent
::
tearDown
();
}
/**
* Sets up test rows.
*/
protected
function
setUpTestRows
()
{
$collection
=
$this
->
getConnection
()
->
getCollection
(
'customer'
);
$rows
=
[];
for
(
$i
=
1
;
$i
<=
10
;
$i
++
)
{
$rows
[]
=
[
'name'
=>
'name'
.
$i
,
'address'
=>
'address'
.
$i
,
];
}
$collection
->
batchInsert
(
$rows
);
}
// Tests :
public
function
testAll
()
{
$connection
=
$this
->
getConnection
();
$query
=
new
Query
;
$rows
=
$query
->
from
(
'customer'
)
->
all
(
$connection
);
$this
->
assertEquals
(
10
,
count
(
$rows
));
}
public
function
testDirectMatch
()
{
$connection
=
$this
->
getConnection
();
$query
=
new
Query
;
$rows
=
$query
->
from
(
'customer'
)
->
where
([
'name'
=>
'name1'
])
->
all
(
$connection
);
$this
->
assertEquals
(
1
,
count
(
$rows
));
$this
->
assertEquals
(
'name1'
,
$rows
[
0
][
'name'
]);
}
public
function
testIndexBy
()
{
$connection
=
$this
->
getConnection
();
$query
=
new
Query
;
$rows
=
$query
->
from
(
'customer'
)
->
indexBy
(
'name'
)
->
all
(
$connection
);
$this
->
assertEquals
(
10
,
count
(
$rows
));
$this
->
assertNotEmpty
(
$rows
[
'name1'
]);
}
public
function
testInCondition
()
{
$connection
=
$this
->
getConnection
();
$query
=
new
Query
;
$rows
=
$query
->
from
(
'customer'
)
->
where
([
'name'
=>
[
'in'
=>
[
'name1'
,
'name5'
]
]
])
->
all
(
$connection
);
$this
->
assertEquals
(
2
,
count
(
$rows
));
$this
->
assertEquals
(
'name1'
,
$rows
[
0
][
'name'
]);
$this
->
assertEquals
(
'name5'
,
$rows
[
1
][
'name'
]);
}
public
function
testOrCondition
()
{
$connection
=
$this
->
getConnection
();
$query
=
new
Query
;
$rows
=
$query
->
from
(
'customer'
)
->
where
([
'name'
=>
'name1'
])
->
orWhere
([
'address'
=>
'address5'
])
->
all
(
$connection
);
$this
->
assertEquals
(
2
,
count
(
$rows
));
$this
->
assertEquals
(
'name1'
,
$rows
[
0
][
'name'
]);
$this
->
assertEquals
(
'address5'
,
$rows
[
1
][
'address'
]);
}
public
function
testOrder
()
{
$connection
=
$this
->
getConnection
();
$query
=
new
Query
;
$rows
=
$query
->
from
(
'customer'
)
->
orderBy
([
'name'
=>
SORT_DESC
])
->
all
(
$connection
);
$this
->
assertEquals
(
'name9'
,
$rows
[
0
][
'name'
]);
}
}
\ No newline at end of file
tests/unit/extensions/mongo/QueryTest.php
View file @
9da7a80f
...
...
@@ -36,6 +36,88 @@ class QueryTest extends MongoTestCase
$this
->
assertEquals
(
$from
,
$query
->
from
);
}
public
function
testWhere
()
{
$query
=
new
Query
;
$query
->
where
([
'name'
=>
'name1'
]);
$this
->
assertEquals
([
'name'
=>
'name1'
],
$query
->
where
);
$query
->
andWhere
([
'address'
=>
'address1'
]);
$this
->
assertEquals
(
[
'name'
=>
'name1'
,
'address'
=>
'address1'
],
$query
->
where
);
$query
->
orWhere
([
'name'
=>
'name2'
]);
$this
->
assertEquals
(
[
'or'
=>
[
[
'name'
=>
'name1'
,
'address'
=>
'address1'
],
[
'name'
=>
'name2'
]
]
],
$query
->
where
);
$query
->
orWhere
([
'name'
=>
'name3'
]);
$this
->
assertEquals
(
[
'or'
=>
[
[
'name'
=>
'name1'
,
'address'
=>
'address1'
],
[
'name'
=>
'name2'
],
[
'name'
=>
'name3'
]
]
],
$query
->
where
);
$query
->
andWhere
([
'address'
=>
'address2'
]);
$this
->
assertEquals
(
[
'or'
=>
[
[
'name'
=>
'name1'
,
'address'
=>
'address1'
],
[
'name'
=>
'name2'
],
[
'name'
=>
'name3'
]
],
'address'
=>
'address2'
],
$query
->
where
);
$query
->
orWhere
([
'name'
=>
'name4'
]);
$this
->
assertEquals
(
[
'or'
=>
[
[
'or'
=>
[
[
'name'
=>
'name1'
,
'address'
=>
'address1'
],
[
'name'
=>
'name2'
],
[
'name'
=>
'name3'
]
],
'address'
=>
'address2'
],
[
'name'
=>
'name4'
]
],
],
$query
->
where
);
}
public
function
testOrder
()
{
$query
=
new
Query
;
...
...
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