Mongo Query in Lithium - mongodb

db.tickers.aggregate(
{ $project:
{_id: 0,
year: {$year: '$date'},
month: {$month: '$date'},
day: {$dayOfMonth: '$date'},
hour: {$hour: '$date'},
avg: '$ticker.avg'
}
},
{ $group: {
_id: { year: '$year', month: '$month', day: '$day', hour: '$hour' },
avg: { $avg: '$avg' }
}
},
{ $sort: {
'year':1, month:1, day:1, hour:1
}
}
);
How do you write the above query in Lithium?
I have tried:
$mongodb = Connections::get('default')->connection;
$tick = Tickers::connection()->connection->command(array(
'aggregate' => 'tickers',
'pipeline' => array(
'_id'=>null,
array('year' => array('$year' => '$date')),
array('month' => array('$month' => '$date')),
array('day' => array('$dayOfMonth' => '$date')),
array('hour' => array('$hour' => '$date')),
array('avg' => '$ticker.avg'),
),
array( '$group' => array( '_id' => array(
'year'=>'$year',
'month'=>'$month',
'day'=>'$day',
'hour'=>'$hour'
),
'avg' => array('$avg' => '$ticker.avg'),
),
array('$sort'=>array(
'year'=>1,
'month'=>1,
'day'=>1,
'hour'=>1
))
)
));
This is reply to the question, I had mongodb: find summary of records
The answer to the question find-summary of records, is correct, but I cannot place it in Lithium.
Thanks in advance :)

You forgot the $project level of the object. Try this instead:
$tick = Tickers::connection()->connection->command(array(
'aggregate' => 'tickers',
'pipeline' => array(
array( '$project' => array(
'_id' => 0,
'year' => array('$year' => '$date'),
'month' => array('$month' => '$date'),
'day' => array('$dayOfMonth' => '$date'),
'hour' => array('$hour' => '$date'),
'avg' => '$ticker.avg',
)),
array( '$group' => array( '_id' => array(
'year'=>'$year',
'month'=>'$month',
'day'=>'$day',
'hour'=>'$hour'
),
'avg' => array('$avg' => '$ticker.avg'),
)),
array('$sort'=>array(
'year'=>1,
'month'=>1,
'day'=>1,
'hour'=>1
))
)
));

Related

MongoDB query $lookup with prefix

I have two collection rounds and summaries
A record in rounds looks like
{
"_id": "2018-04",
"name": "Round 2018-04"
}
A record in summaries look like
{
"phase": "round:2018-04",
"userId": NumberLong(66325),
}
I want to query summaries and lookup into rounds joining based on phase of summaries into _id of rounds
PROBLEM: It will be pretty simple if there was no prefix of round: in phase.
Is there anyway to do this?
This is my code so far.
$cursor = $this->mongo->selectCollection('summaries')->aggregate([
array('$match' => []),
array(
'$lookup' => [
'from' => 'rounds',
'localField' => 'phase',
'foreignField' => '_id',
'as' => 'roundDetail'
]
),
array(
'$unwind' => '$roundDetail',
),
array(
'$project' => [
'userId' => 1,
'roundDetail.name' => 1
]
)
]);
MongoDB version 3.4.16
You can use substrBytes to remove characters from the string.
$cursor = $this->mongo->selectCollection('summaries')->aggregate([
array('$match' => []),
array('$addFields' => [ 'phase' => [ '$substrBytes' => [ '$phase', 6, 7 ] ] ] ),
array(
'$lookup' => [
'from' => 'rounds',
'localField' => 'phase',
'foreignField' => '_id',
'as' => 'roundDetail'
]
),
array(
'$unwind' => '$roundDetail',
),
array(
'$project' => [
'userId' => 1,
'roundDetail.name' => 1
]
)
])

How to implement MongoDB query in Laravel 5?

I created mongodb query which I have to use in laravel controller.
My query is
db.PMS.aggregate([
{ $match: { "PanelID": "A00898" } },
{
$project: { EventTS: 1, MainsPower: 1, }
},
{
$unwind: {
path: "$MainsPower",
includeArrayIndex: "arrayIndex",
preserveNullAndEmptyArrays: true
}
},
{
$project: {
MainsPower: 1,
timestamp: {
"$add": [
"$EventTS",
{ "$multiply": [ 60000, "$arrayIndex" ] }
]
}
}
}
]);
I tried to use this query in a laravel function but I am little confused. Please help me how to implement this query in laravel.
Perform raw expressions on the internal MongoCollection object to run the aggregation:
$result = DB => collection('PMS')->raw(function ($collection){
return $collection->aggregate(array(
array( '$match' => array( "PanelID" => "A00898" ) ),
array( '$project' => array( 'EventTS' => 1, 'MainsPower' => 1 ) ),
array(
'$unwind' => array(
'path' => "$MainsPower",
'includeArrayIndex' => "arrayIndex",
'preserveNullAndEmptyArrays' => true
)
),
array(
'$project' => array(
'_id' => 0,
'MainsPower' => 1,
'timestamp' => array(
"$add" => array(
"$EventTS",
array( "$multiply" => array( 60000, "$arrayIndex" ) )
)
)
)
)
));
});

Get sum of quantity in mongodb using yii2 framework

How can i sum of quantity using mongodb query in yii2?
In my database there are entries like below:
{
'_id': ObjectId("560e36f91e4acbf113d14f1f"),
'user_id': '55ded7c31e4acbea3c8b4567',
'money': '1.99',
'quantity': '1',
'purchased_date_time': '2015-10-02 07:49:13'
}
{
'_id': ObjectId("560e36f71e4acbf113d14f1e"),
'user_id': '55ded7c31e4acbea3c8b4567',
'money': '1.99',
'quantity': '1',
'purchased_date_time': '2015-10-02 07:49:11'
}
{
'_id': ObjectId("560d17381e4acbf013d14f1e"),
'user_id': '55ded7c31e4acbea3c8b4567',
'money': '4.99',
'quantity': '3',
'purchased_date_time': '2015-10-01 11:21:28'
}
I want to sum of quantity where user_id = 55ded7c31e4acbea3c8b4567.
What i tried is:
$collection = Yii::$app->mongodb->getCollection('purchase');
$result = $collection->aggregate(
array( '$match' => array( 'user_id' => '55ded7c31e4acbea3c8b4567') ),
array( '$group' => array( '_id' => NULL,
'quantity' => array( '$sum' => (int)'$quantity' )
))
);
But always i am getting this result:
<pre>Array
(
[0] => Array
(
[_id] =>
[quantity] => 0
)
)
</pre>
Can anyone help?
Remove int then after check......
I solved my issue after remove it
$collection = Yii::$app->mongodb->getCollection('purchase');
$result = $collection->aggregate(
array( '$match' => array( 'user_id' => '55ded7c31e4acbea3c8b4567') ),
array( '$group' => array( '_id' => NULL,
'quantity' => array( '$sum' => '$quantity' )
))
);

How to make this MongoDB aggregation return key:value?

I have this aggregation:
$out = $db->stats->aggregate (
array('$match' => $where),
,array( '$group' =>
array( "_id" => '$traffic.source',
'count'=> array('$sum' => 1)
)
)
,array( '$project' =>
array( "_id" => 0,
'type' => '$_id',
'count' => '$count'
)
)
);
which returns an array with:
[{type:sourceA, count:2},{type:sourceB, count:6}...]
Is it possible to make it return:
[sourceA:2, sourceB:6,....] without looping the array afterwords?

Perl printing second level hash keys in a nested hash

How do I print all my second level hash keys (sig_qtr, date, range, etc.) given a hash like such:
my $xml = XMLin("./${spec_file}", ForceArray => ['range', 'constant', 'question', 'date', 'sig_yr', 'sig_qtr', 'sig_mth'], KeyAttr => {});
print Dumper $xml->{entities};
print dumper output of hash:
$VAR1 = {
'sig_qtr' => [
{
'name' => 'q1',
'label' => 'q1'
},
{
'name' => 'q4',
'label' => 'q4'
}
],
'date' => [
{
'name' => 'y2_mth',
'label' => 'pryr_mth_curr'
},
{
'name' => 'y3_pod6_qtr4',
'label' => 'curr_qtd4'
}
],
'range' => [
{
'name' => 'y0_jun',
'end' => '20100631',
'start' => '20100601'
},
{
'name' => 'y3_oct',
'end' => '20131031',
'start' => '20131001'
}
],
'constant' => [
{
'spec' => '99999999 and 99999999',
'name' => 'none_sixmth'
}
],
'sig_yr' => [
{
'name' => 'y1_sig',
'label' => 'ye11'
},
{
'name' => 'y3_sig',
'label' => 'ytd'
}
],
'sig_mth' => [
{
'name' => 'y3_nov',
'label' => 'nov12'
},
{
'name' => 'y3_oct',
'label' => 'oct13'
}
],
'question' => [
{
'name' => 'ltrq',
'label' => 'q9'
},
{
'name' => 'nextprod',
'label' => 'q12a'
}
],
'backfill' => {
'label' => 'bf_period'
},
'year' => {
'current' => '2013'
}
};
would be even better if keys are put into an array.
Thanks.
print "$_\n" for keys %{ $xml->entities };
To put them into an array,
my #keys = keys %{ $xml->entities };