Is there a way to perform a raw query (just as you can do with MySQL) in Doctrine with MongoDB?
I'm trying to do this:
db.report.aggregate([{"$group" : {_id:"$content", count:{$sum:1}}}])
It doesn't seem to be a native aggregate function in Doctrine either, is it?
Following did the trick for me
$dbName = $this->container->getParameter('mongo_db_name');
$connection = $this->container->get('doctrine_mongodb')->getConnection();
$mongo = $connection->getMongo();
$db = $mongo->selectDB($dbName);
$results = $db ->command([
'aggregate' => 'report',
'pipeline' => [
['$group' => ['_id' => '$content', 'count' => ['$sum' => 1]]]
]
]);
return $results;
Not sure about native Doctrine function, but in case of aggregations I'd prefer to have RAW JSON output, because it's mostly used to render out some charts.
I needed to use an advanced version of a $lookup stage, but sadly, didn't because its lookup() method adds just a basic version of a stage like:
public function getExpression(): array
{
return [
'$lookup' => [
'from' => $this->from,
'localField' => $this->localField,
'foreignField' => $this->foreignField,
'as' => $this->as,
],
];
}
An obvious solution would be to provide a custom version of Stage/Lookup.php class, but I didn't want to create a separate file for such a small thing, so I decided to go with inline class:
$lookupExpr = [
'$lookup' => [...],
];
$aggregationBuilder->addStage(new class($lookupExpr, $aggregationBuilder) extends Aggregation\Stage {
public function __construct(private array $lookupExpr, Builder $builder) {parent::__construct($builder);}
public function getExpression(): array
{
return $this->lookupExpr;
}
});
In Doctrine ODM 2.0, the underlying connection is handled by the mongodb/mongodb package instead of doctrine/mongodb. As such, you can get the connection though doctrine ManagerRegistry::getConnection(), then use the command function using the mongodb library:
use Doctrine\Bundle\MongoDBBundle\ManagerRegistry;
class Test {
function execute(ManagerRegistry $mr) {
$database= $mr->getConnection()->db_name;
$cursor = $database->command([
'geoNear' => 'restos',
'near' => [
'type' => 'Point',
'coordinates' => [-74.0, 40.0],
],
'spherical' => 'true',
'num' => 3,
]);
$results = $cursor->toArray()[0];
var_dump($results);
}
}
In my case i use aggregation
$db = $mongo->selectDB('ostrov_sync');
$dbTable = $mongo->selectCollection($db, 'sync_task');
$results = $dbTable->aggregate([
[
'$match' => [
'payloadHash' => [
'$eq' => '0000cfdc-c8cf-11e9-9485-000c29d1ed7a',
],
],
]
]);
dump(results);
Related
I try to use Zend_Cache (first try) to save information about user grants. The idea and most of the source code comes from Oleg Krivtsovs tutorial.
I get an error, if I try to retrieve my cache.
Call to a member function getItem() on array
Here the implementation of FilesystemCache, in my global.php
'caches' => [
'FilesystemCache' => [
'adapter' => [
'name' => Filesystem::class,
'options' => [
// Store cached data in this directory.
'cache_dir' => './data/cache',
// Store cached data for 1 hour.
'ttl' => 60*60*1
],
],
'plugins' => [
[
'name' => 'serializer',
'options' => [
],
],
],
],
],
Here my factory class:
<?php
namespace User\Service;
use User\Controller\Plugin\AuthPlugin;
use User\Model\GrantsTable;
use User\Model\UserTable;
use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\Factory\FactoryInterface;
use Interop\Container\ContainerInterface;
class AccessControlFactory implements FactoryInterface {
public function __invoke(ContainerInterface $container, $requestedName, array $options = null) {
$config = $container->get('config');
$userTable = $container->get(UserTable::class);
$grantsTable = $container->get(GrantsTable::class);
$cache = $config['caches']['FilesystemCache'];
$userplugin = $container->get(AuthPlugin::class);
// $authentication = $container->get( \Zend\Authentication\AuthenticationService::class);
return new AccessControl($userTable, $grantsTable, $cache, $userplugin);//, $authentication
}
}
Now in the init function within my AccessControl Service, I try to retrieve from the cache:
$this->cache->getItem('rbac_container', $result);
There I get the above error.
Any help with a bit of explanation would be appreciated.
What you're injecting to the AccessControl constructor is an array, not a cache implementation, because $config['caches']['FilesystemCache'] returns an array of FilesystemCache options (adapter, plugins, etc.). What you're supposed to do is fetch the cache implementation via the ContainerInterface, like this:
$cache = $container->get('FilesystemCache');
Then the ContainerInterface will depend on StorageCacheAbstractServiceFactory to find your requested cache configs and return the class for you.
How to use aggregate and $lookup with php 7 mongo driver manager.
How to convert the following mongo command to php
db.a.aggregate([{$lookup:{from:"b",localField:"business_id",foreignField:"_id",as:"contact"}}])
Also recommend good reference tutorials.
This code worked
$mng = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$command = new MongoDB\Driver\Command([
'aggregate' => 'a',
'pipeline' => [
['$lookup' => ["from" => "b","localField" => "business_id","foreignField" => "_id","as" => "contact"]],
],
]);
$cursor = $mng->executeCommand('test', $command);
Try something like this:
$mongo->db->a->aggregate([
['$lookup' => ['from' => 'b', 'localField' => 'business_id', 'foreignField' => '_id', 'as' => 'contact'] ]
]);
PHP7.2
MongoDB 4.2
I took reference from #Jibin Mathew' answer but I got some errors.
then I added
'cursor' => new stdClass,
this line in code.
Now it's working properly.
//mongo database join example
public function test_join() {
global $mng;
global $dbname;
$pipeline = [['$lookup' => ["from" => "b","localField" => "business_id","foreignField" => "_id","as" => "contact"]]];
$aggregate = new \MongoDB\Driver\Command([
'aggregate' => 'a',
'cursor' => new stdClass,
'pipeline' => $pipeline,
]);
$cursor = $mng->executeCommand($dbname, $aggregate);
return $cursor;
}
I want to get data from mongodb by using MongoDB PHP7.1 Driver with the help of $or or $and clause in filter. I have tried to construct query to do the same but that didn't work.
Here is my sample code here:
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
try {
$filter = [
'$or' => [
'age' => [ '$gt' => 40],
'name' => 'abc'
]
];
$query = new MongoDB\Driver\Query($filter);
$rows = $manager->executeQuery("test.users", $query);
foreach ($rows as $key => $val) {
print_r($val);
}
} catch(MongoDB\Driver\Exception $e) {
echo $e->getMessage(), "\n";
exit;
}
The above code gives me below error:
Fatal error: Uncaught MongoDB\Driver\Exception\ConnectionException: $or must
be an array in C:\xampp\htdocs\local\demo.php:50 Stack trace: #0
C:\xampp\htdocs\local\demo.php(50): MongoDB\Driver\Manager-
>executeQuery('test.users', Object(MongoDB\Driver\Query)) #1 {main} thrown
in C:\xampp\htdocs\local\demo.php on line 50
Please help me to understand what I am doing wrong.
Adding to answer from #Veeram: Had this as my filter, which did not work:
$filter = [
'$and' =>
['date' => ['$gte' => $start_date]],
['date' => ['$lte' => $end_date]]
];
added the extra [] as #Veeram suggested. This configuration works for $and:
$filter = [
'$and' => [
['date' => ['$gte' => $start_date]],
['date' => ['$lte' => $end_date]]
]
];
you can do this also
$result=$collections->
find(array('$and=>array(array('date'=>array('$gte'=>$start_date)
),array('date'=>array('$lte'=>$end_date))));
I want to expand this question.
Basically I have users endpoint. But I am also returning data from the related profiles table. I am not expanding with profiles, I always want to return it. So I have fields method like this:
public function fields()
{
$fields = parent::fields();
$fields[] = 'profile';
return $fields;
}
When I do GET request and demand sorting by profile.created_at field and user.status, it does not sort by profile.created_at.
GET v1/users?sort=-profile.created_at,status
Can this be achieved somehow ?
This is my current code:
/** #var $query ActiveQuery */
$query = User::find();
// get data from profile table
$query->innerJoinWith('profile');
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => ['defaultOrder' => ['id' => SORT_DESC]],
'pagination' => [
'pageSize' => 10,
],
]);
return $dataProvider;
You have overridden 'sort' parameter of ActiveDataProvider. To keep default behaviour of Sort object and change defaultOrder property, create an instance, such as:
$sort = new \yii\data\Sort([
'attributes' => [
'profile.created_at',
],
'defaultOrder' => ['id' => SORT_DESC],
]);
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => $sort,
'pagination' => [
'pageSize' => 10,
],
]);
The following is the json array I have in a collection called claims in MongoDB.
{
"xmllisting_id": "537f371fb2e380922fff0e2c",
"pharmacyfiles_id": "537f3402b2e380732aa6032d",
"claim": {
"MemberID": "097110330047532601",
"PatientShare": "0",
},
"modified": ISODate("2014-05-23T13:12:17.191Z"),
"created": ISODate("2014-05-23T13:12:17.192Z")
}
I need to find all claims with a specified MemberID.I have tried the following in CakePHP without any success.
$claims = $claimobj->find(
'all',
array(
'conditions' => array(
'claim' => array('MemberID' => '097110330047532601')
)
)
);
How can I do it?
Finding "nested" details in MongoDB usually requires "dot notation". Otherwise you are actually asking for an object that has "exactly" the key and "only" the key you are specifying to match. Which of course it does not, as there is more information there:
$claims = $claimobj->find(
'all',
array(
'conditions' => array(
'claim.MemberID' => '097110330047532601'
)
)
);
So the path is "claim.MemberID" and not 'claim' => array('MemberID' => '097110330047532601' ) as you have written.