Mongodb with PHP aggregate() like cursor - php

I need to iterate over large result set of Mongodb collection in PHP. But I am getting timeout error. How to use it like a cursor till result is not finished and parse returned documents in chunks? The pipeline looks like
$mongoPipeline = [
[
'$match' => [
'global_campaign_id' => ['$in' => $campaigns_ids]
]
],
[
'$group' => [
'_id' => [
'global_campaign_id' => '$global_campaign_id',
'device_id' => '$device_id',
'partner_id' => '$partner_id',
],
'date_last' => ['$max' => '$date_created'],
'partner_id' => ['$first' => '$server'],
'campaign_id' => ['$first' => '$global_campaign_id'],
'device_id' => ['$first' => '$device_id']
]
],
[
'$limit' => 5,
],
];
$options = [
'allowDiskUse' => true,
//'maxTimeMS' => 1000 * 60 * 1,
'useCursor' => true,
//'explain' => true,
];
$result = [];
/** #var Cursor $cursor */
$cursor = $this->mongoDb->{$collection}->aggregate($pipeline, $options);
$cursor->setTypeMap(['root' => 'array', 'document' => 'array', 'array' => 'array']);
foreach ($result as $doc) $result[] = $this->parseDocument($doc);
return $result;
If I use $cursor->toArray() if fall down on timeoutError.
How this script should look like?

Related

Is it possible to use specific index in Mongodb using PHP?

Can somebody tell me please if is possible to force Mongodb to use specific index from PHP script? I have something like this:
$mongoPipeline = [
[
'$match' => [
'global_campaign_id' => ['$in' => $campaigns_ids]
]
],
[
'$group' => [
'_id' => [
'global_campaign_id' => '$global_campaign_id',
'device_id' => '$device_id',
'partner_id' => '$partner_id',
],
'date_last' => ['$max' => '$date_created'],
'partner_id' => ['$first' => '$server'],
'campaign_id' => ['$first' => '$global_campaign_id'],
'device_id' => ['$first' => '$device_id']
]
]
];
$options = [
'allowDiskUse' => true,
'maxTimeMS' => 1000 * 60 * 1,
'explain' => true,
];
$cursor = $this->mongoDb->{$collection}->aggregate($pipeline, $options);
Is it possible to add index to options object? If I use explain it seems it does not use an index prepared for this query. It is compoud index:
global_campaign_id: 1, device_id: 1, partner_id: 1, date_created: 1

something wrong with my loop from aggregation mongodb

i want to return the result of data from my aggregation mongodb for datatable, when i try to debug the aggregation result it return an array(with much data in it), then i just loop it but the return only one array data.. what happens here?
here my code:
$aggregation = [
[ '$match' => $condition ],
[
'$project' => [
'_id' => 1,
'id' => 1,
'companyid' => 1,
'user' => [
'employeeid' => 1,
'yearin' => 1,
'department' => 1,
'status' => 1
]
]
]
];
$appGeneralComponent = new AppGeneralComponent();
$result = $appGeneralComponent->datatableQuery($this->employeeCollection, $aggregation, []);
$result['data'] = array_map(function ($value) {
foreach ($value['user'] as $key => $v) {
return [
'uid' => Encoder::Encrypt($value['_id']),
'employeeid' => $v['id'],
'yearin' => $v['yearin'],
'department' => $v['department'],
'status' => $v['status']
];
}
}, $result['data']);
//here only return 1 array data which is it should 10 data
echo "<pre>";var_dump($result);exit;

Mongo $addToSet an Array

I have a working query:
$offenses = \App\LawCase::raw(function ($collection) {
return $collection->aggregate([
[
'$match' => ['active' => true, 'type' => 'criminal', 'current_offense_literal'=> ['$exists' => true]]
],
[
'$group' => ['_id' => '$current_offense_category', 'offense_literals' => ['$addToSet' => '$current_offense_literal']]
]
]);
});
I just want to add an additional value to the addToSet above. For example Each current_offense_literal also has a current_offense_literal_value and I would like to add that along with current_offense_literal.
What i tried:
$offenses = \App\LawCase::raw(function ($collection) {
return $collection->aggregate([
[
'$match' => ['active' => true, 'type' => 'criminal', 'current_offense_literal'=> ['$exists' => true]]
],
[
'$group' => ['_id' => '$current_offense_category', 'offense_literals' => ['$addToSet' => ['$current_offense_literal'=>['$push'=> '$current_offense_literal_value']]]]
]
]);
});
But I am getting:
Unrecognized expression '$current_offense_literal'.
try doing this,
$offenses = \App\LawCase::raw(function ($collection) {
return $collection->aggregate([
[
'$match' => ['active' => true, 'type' => 'criminal', 'current_offense_literal'=> ['$exists' => true]]
],
[
'$group' => ['_id' => '$current_offense_category', 'offense_literals' => ['$addToSet' => ['current_offense_literal'=>'$current_offense_literal', 'current_offense_literal_value' =>'$current_offense_literal_value']]]
]
]);
});

find and update a document in elasticsearch2 using php

I am trying to find a document using ElasticSearch and update a field in it. The code is:
require_once 'vendor/autoload.php';
$client = Elasticsearch\ClientBuilder::create()->build();
$params = [
'index' => 'myIndex',
'type' => 'myCollection',
'body' => [
'query'=> [
'match'=> [
'accessToken' => $accessToken
]
] ,
'script' => 'ctx._source.deviceId= deviceId',
'params' => [
'deviceId' => $deviceId
],
'upsert' => [
'counter' => 1
]
]
];
The code is giving 500 Internal Error. Any idea what am I missing?
If you want to increase the value of deviceid by 1 (mean if value of deviceid is 4 then u can increase it to 5 by adding 1 to it ),then follow below code
'script' => 'ctx._source.deviceId= deviceId',
replace with
'script' => 'ctx._source.counter += deviceId',
Example:
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'body' => [
'script' => 'ctx._source.counter += count',
'params' => [
'count' => 4
],
'upsert' => [
'counter' => 1
]
]
];
$response = $client->update($params);
Check i Elasticsearch php

Recursively Create an Array from another Array

I am trying to make a multi-dimensional array build an array path adding the hr field so it looks like this:
I just can't figure out how to add the totals, nor create a sub-array so the dot notation in an option too. My goal is to get something like this:
[1] => [1][2][1][5][0][6] = 35 (the second child path "1")
[1] => [1][2][1][5][0][7] = 25
or Something like this:
array (
[children.0.children.0.children.0.total] = 20
[children.0.children.1.children.1.total] = 35
// etc
)
The complicated part is that it goes in different directions and I want to know what is the highest and lowest total based on the path:
==> Run Code Here or Copy/Paste
// -------------
// The Flattener
// -------------
function doit($myArray) {
$iter = new RecursiveIteratorIterator(new RecursiveArrayIterator($myArray));
$result = array();
foreach ($iter as $leafKey => $leafValue) {
$keys = array();
foreach (range(0, $iter->getDepth()) as $depth) {
$keys[] = $iter->getSubIterator($depth)->key();
}
$result[ join('.', $keys) ] = $leafValue;
}
return $result;
}
// -------------
// Example Tree
// -------------
$tree = [
'id' => 1,
'type' => 'note',
'data' => [],
'children' => [
[
'id' => 2,
'type' => 'wait',
'data' => [
'hr' => 10,
],
'children' => [
[
'id' => 3,
'type' => 'wait',
'data' => [
'hr' => 10,
],
'children' => [
'id' => 4,
'type' => 'exit',
'data' => [],
'children' => []
]
],
[
'id' => 5,
'type' => 'note',
'data' => [
'hr' => 10,
],
'children' => [
[
'id' => 6,
'type' => 'wait',
'data' => [
'hr' => 10,
],
'children' => []
],
[
'id' => 7,
'type' => 'exit',
'data' => [],
'children' => []
],
]
]
],
]
]
];
$result = doit($tree);
print_r($result);
This seems to work, I found it somewhere googling all day.
array_reduce(array_reverse($keys), function($parent_array, $key) {
return $parent_array ? [$key => $parent_array] : [$key];
}, null);

Categories