I have a data of stores, report_type is every type of data
- type 3 stored how much money that clients buy and how many transaction.
- type 5 stored how many people and average age of them.
I need an array like this:
"report_type3"
(
[_id] => 2441
[amountclient] => 3749078452,
[trans] => 1000
),
(
[_id] => 2442
[amountclient] => 15533754,
[trans] => 900
)
,
"report_type5"
(
[_id] => 2441
[people] => 120,
[avgage] => 23,
),
(
[_id] => 2441
[people] => 120,
[avgage] => 23,
)
My query looks like this, but it's not working
$cursor = $collection->aggregate([
['$match' => [ 'id_station' => ['$in' => $store ], 'report_type' => 3,
'date' => ['$gte'=> new MongoDB\BSON\UTCDateTime(strtotime("2017-07-01")*1000), '$lte'=> new MongoDB\BSON\UTCDateTime(strtotime("2017-08-05")*1000)]
]
],
['$group' => [
'_id' => [ 'id_station' => '$id_station', 'receiptid' => '$receiptid' ],
'amount' => [ '$sum' => '$amount' ]
]], .... *I group by receiptid because there are many items in one clients.*
[ '$group' => [
'_id' => '$_id.id_station',
'amount' => [ '$sum' => '$amount' ],
'trans' => [ '$sum' => '$trans' ]
]],
[
'$project' => [
'report_type3' => ['_id','$amountclient','$trans']
]
],
['$match' => [ 'id_station' => ['$in' => $store ], 'report_type' => 5,
'date' => ['$gte'=> new MongoDB\BSON\UTCDateTime(strtotime("2017-07-01")*1000), '$lte'=> new MongoDB\BSON\UTCDateTime(strtotime("2017-08-05")*1000)]
]
],
[ '$group' => [
'_id' => ['$_id.id_station', 'area_type' => '$area_type'],
'people' => [ '$sum' => '$people' ],
'avgage' => [ '$avg' => '$age' ]
]],
[
'$project' => [
'report_type5' => [ '_id', 'people', 'avgage' ]
]
]
]);
Could you please help me on this?
Related
I want to know how can I propery filter field from another collection that is linked from main collection.
Here is my filter values
if(!empty($filterDataBuyer['price'])){
$findArray['price'] = intval($filterDataBuyer['price']);
}
if(!empty($filterDataBuyer['search'])){
$findArray['full_name'] = $filterDataBuyer['search'];
}
}
$findArray['type'] = 'buyer';
The price and type works fine but the full_name does not work
And here is for getting the data
$getData = [
[
'$match' => $findArray
],
[
'$project' => [
'_id' => ['$toString' => '$_id'],
'type' => '$type',
'created_date' => '$created_date',
'offer_id' => '$offer_id',
'buyer_id' => '$buyer_id',
'traveler_id' => '$raveler_id',
'order_id' => '$order_id',
'price' => '$price'
]
],
[
'$lookup' => [
'from' => 'users',
'let' => [
'admin_id' => ['$toObjectId' => '$buyer_id'],
],
'pipeline' => [
[
'$match' => [
'$expr' => [
'$eq' => [
'$_id',
'$$admin_id'
]
],
],
],
[
'$project' => [
'_id' => ['$toString' => '$_id'],
'profile_image' => '$profile_image',
'full_name' => '$full_name'
]
],
],
'as' => 'profileData'
]
],
What I want to do is if full_name field is available, it could also filter the result by it, price and type can filter successfully but full_name is not. Result returns only if full_name has value on it.
My PHP version is 7.4.27 and mongodb extension is 1.12.0
This is just two collections, payment_details and users where payment_details has buyer_id field that is reference to users id field
From mongocompass:
payment_details:
users:
Full Code update:
if(!empty($filterDataBuyer['price'])){
/* FLIGHT-31 fix */
$findArray['price'] = intval($filterDataBuyer['price']);
}
if(!empty($filterDataBuyer['search'])){
$findArray['full_name'] = $filterDataBuyer['search'];
}
$findArray['type'] = 'buyer';
$buyer_trasections = $db->payment_details->find($findArray);
$buyerRes_trasections = iterator_to_array($buyer_trasections);
$getData = [
[
'$match' => $findArray
],
[
'$project' => [
'_id' => ['$toString' => '$_id'],
'type' => '$type',
'created_date' => '$created_date',
'offer_id' => '$offer_id',
'buyer_id' => '$buyer_id',
'traveler_id' => '$raveler_id',
'order_id' => '$order_id',
'price' => '$price'
]
],
[
'$lookup' => [
'from' => 'users',
'let' => [
'admin_id' => ['$toObjectId' => '$buyer_id'],
],
'pipeline' => [
[
'$match' => [
'$expr' => [
'$eq' => [
'$_id',
'$$admin_id'
]
],
],
],
[
'$project' => [
'_id' => ['$toString' => '$_id'],
'profile_image' => '$profile_image',
'full_name' => '$full_name'
]
],
],
'as' => 'profileData'
]
],
[
'$skip' => $page
],
[
'$limit' => $config['per_page'],
],
[
'$sort' => [ 'created_date'=> -1]
]
];
$buyer_trasec = $db->payment_details->aggregate($getData);
$buyerRes_trasec = iterator_to_array($buyer_trasec);
echo "<pre>";print_r($buyerRes_trasec);exit;
And this is the sample, first result for echo "<pre>";print_r($buyerRes_trasec);exit;
MongoDB 3.4
I have a project and project_permission collections. The project_permission collection contains permissions to the projects for some users. A single user can have multiple different permissions to the project.
[
'$lookup' => [
'from' => ProjectPermission::collectionName(),
'localField' => '_id',
'foreignField' => 'project_id',
'as' => 'project_permissions'
]
],
[
'$project' => [
// ... irrelevant fields here
'permissions' => '$project_permissions'
]
],
this is how the project query results looks like without filtering:
// other project results
// ... other fields
'permissions' => [
0 => [
'_id' => '5d2873aafa873b2b7c000fad'
'project_id' => '56a9e5c5d18cacc72a485839'
'user_id' => '562f6bfc05dfe9570fb6e427'
'permission' => 'read'
'created_at' => 1562932138
'updated_at' => 1562932139
]
1 => [
'_id' => '5d2879fdfa873b2b7c000fbd'
'project_id' => '56a9e5c5d18cacc72a485839'
'user_id' => '562f6bfc05dfe9570fb6e427'
'permission' => 'write'
'created_at' => 1562932139
'updated_at' => 1562932140
]
2 => [
'_id' => '5db960b5fa873b1604005e8e'
'project_id' => '56a9e5c5d18cacc72a485839'
'user_id' => '582b30dd1e634e6362e1b504'
'permission' => 'write'
'created_at' => 1572430005
'updated_at' => 1572430005
]
]
What I would like to achieve is to return with only those projects where the client - who requested the query - has a specific permission to the project, for example write.
The way I tried it:
pipeline: [
0 => [
'$match' => [
// not related to the problem
]
]
1 => [
'$match' => [
'$and' => [
0 => [
'shared_permissions' => [
'$eq' => true
]
]
1 => [
'$or' => [
0 => [
'project_permissions' => [
'$exists' => true
'$ne' => []
]
]
1 => [
'owner_id' => [
'$ne' => MongoDB\BSON\ObjectId#1
(
[oid] => '582b30dd1e634e6362e1b504'
)
]
]
]
]
]
]
]
2 => [
'$lookup' => [
'from' => 'project_permission'
'localField' => '_id'
'foreignField' => 'project_id'
'as' => 'project_permissions'
]
]
3 => [
'$project' => [
// more not important fields here
'shared_permissions' => 1
'permissions' => [
'$map' => [
'input' => [
'$filter' => [
'input' => '$project_permissions'
'as' => 'project_permission'
'cond' => [
'$and' => [
0 => [
'$eq' => ['$$project_permission.user_id', MongoDB\BSON\ObjectId#1
(
[oid] => '582b30dd1e634e6362e1b504'
)
]
1 => [
'$eq' => ['$$project_permission.permission', 'write']
]
]
]
]
]
'as' => 'project_permission'
'in' => [
'user_id' => '$$project_permission.user_id'
'permission' => '$$project_permission.permission'
]
]
]
]
]
]
For this I almost get the correct response:
[
0 => [
'_id' => '56a9e5c5d18cacc72a485839'
'short_id' => 3
'title' => 'Modified title'
'owner_id' => '562f692a05dfe9560fb6e428'
'updated_at' => 1572435428
'owner_name' => 'Borat Sagdiyev'
'shared_permissions' => true
'permissions' => [
0 => [
'user_id' => '582b30dd1e634e6362e1b504'
'permission' => 'write'
]
]
]
1 => []
]
The problem with this is that empty array, where the result was filtered out - and it wouldn't be a problem if the empty array wouldn't be in the result, because if I use the pagination, then it says two results, instead of one. And we know that in the worst case we would get back an array of empty arrays only.
So what I would like to achieve is this last example results without empty arrays in a way where the pagination will be fine with it too.
ps.: unwind is not an option, because of some structural conventions.
Any ideas?
To perform an equality match between a field from the input documents with a field from the documents of the “joined” collection, the $lookup stage has the following syntax:
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
I trying to group by two different fields in an aggregation in order to avoid duplicating it. I have the below case:
'$project' => [
'type1' => '$field1',
'type2' => '$field2',
'category1' => [
'$cond' => [
['$gt' => ['field3', ' ']],
1,
0
]
],
'category2' => [
'$cond' => [
['$eq' => ['$field4', 1]],
1,
0
]
],
],
],
['$group' => [
'_id' => '$type1',
'total' => ['$sum' => 1],
'category1' => ['$sum' => '$category1'],
'category' => ['$sum' => '$category2']
]
],
['$sort' => ['_id.$type1' => 1, '_id.type1' => 1]]
In the above example I am grouping them by the $field1. Is it possible in the same aggregation to group the same data by $field 2 too?
Yes, its possible.
If you want to group two fields, then the query is as simple as:
db.collection.aggregate([
{$group:{_id:{field1:"$field1", field2:"$field2"}..other accumulators here..}}
])
I am trying to add multiple criterion to ElasticSearch PHP in must clause, but it is giving me a 500 Error.
My params are:
$params = ['index' => 'smartjn',
'type' => 'feed_details',
'size' => 10,
'body' => [
'sort' => [
'sorter' => [
'order' => 'desc',
'mode' => 'max'
]
],
'query' => ['bool' => [
'must' => [
['match' => ['approvalStatus' => 'approved']],
[ '_id' => [
'$lt' => new MongoDB\BSON\ObjectId($documentid)
]
]
],
'must_not' => ['term' => ['muteFeedUserIds' => $userID]],
'must_not' => ['term' => ['muteUserIds' => $userID]]
]
]
]
];
Please note that this works if I remove the second criteria in must clause i.e.
$params = ['index' => 'smartjn',
'type' => 'feed_details',
'size' => 10,
'body' => [
'sort' => [
'sorter' => [
'order' => 'desc',
'mode' => 'max'
]
],
'query' => ['bool' => [
'must' => [
['match' => ['approvalStatus' => 'approved']]
],
'must_not' => ['term' => ['muteFeedUserIds' => $userID]],
'must_not' => ['term' => ['muteUserIds' => $userID]]
]
]
]
];
Any idea what am I missing?
Thanks
check this out.
'query' => ['bool' => [
'must' => [
['match' => ['approvalStatus' => 'approved']],
[ 'ids' => [
'values' => [new MongoDB\BSON\ObjectId($documentid)]
]
]
],
'must_not' => ['term' => ['muteFeedUserIds' => $userID]],
'must_not' => ['term' => ['muteUserIds' => $userID]]
]
If that doesnt work i am giving you the raw as i am not good with elasticphp
{
"query": {
"bool": {
"must": [
{
"ids": {
"type": "type_of_index"
"values": ["AVbqtjXfoKQ0pubF_-NA"]
}
}
]
}
}
}
type is optional
Just add this ids part under must area.
I am trying to get around the 30 second cursor time limit and avoid a MongoCursorTimeoutException by using DB->command method as seen here: MongoCursorTimeoutException for aggregate function
When I try to aggregate, command instantly returns:
array(3) { ["ok"]=> float(0) ["errmsg"]=> string(42) "Invalid input resource, " ["code"]=> int(17138) } There is pretty much no documentation on this and the only think I could find is the source code where the error takes place https://github.com/mongodb/mongo/blob/master/src/mongo/db/pipeline/pipeline.cpp#L327
Can someone please help? The pipeline works fine if I run collection->aggregate(pipeline, options) so I don't think it is the pipeline. My code is below:
$connection = new MongoClient( 'mongodb://user:pass#mydb.biz' );
$summaryDB = $connection->selectDB('Summary');
$summaryCollection = $summaryDB->selectCollection('hitSummary');
//agg pipeline
$pipeline =
[
[
'$match' => [
'date' => [
'$gte' => $weekAgo,
'$lt' => $today,
]
]
], [
'$group' => [
'_id' => [
'client' => '$client',
'date' => '$date',
],
//conversions
'z1is' => [ '$sum' => '$actions.sales.import.z1.count' ],
'z2is' => [ '$sum' => '$actions.sales.import.z2.count' ],
'z3is' => [ '$sum' => '$actions.sales.import.z3.count' ],
'z1ps' => [ '$sum' => '$actions.sales.pixel.z1.count' ],
'z2ps' => [ '$sum' => '$actions.sales.pixel.z2.count' ],
'z3ps' => [ '$sum' => '$actions.sales.pixel.z3.count' ],
'z1as' => [ '$sum' => '$actions.sales.apiOnly.z1.count' ],
'z2as' => [ '$sum' => '$actions.sales.apiOnly.z2.count' ],
'z3as' => [ '$sum' => '$actions.sales.apiOnly.z3.count' ],
'z1ss' => [ '$sum' => '$actions.sales.s2s.z1.count' ],
'z2ss' => [ '$sum' => '$actions.sales.s2s.z2.count' ],
'z3ss' => [ '$sum' => '$actions.sales.s2s.z3.count' ],
//clicks
'z1ic' => [ '$sum' => '$actions.click.import.z1.count' ],
'z2ic' => [ '$sum' => '$actions.click.import.z2.count' ],
'z3ic' => [ '$sum' => '$actions.click.import.z3.count' ],
'z1pc' => [ '$sum' => '$actions.click.pixel.z1.count' ],
'z2pc' => [ '$sum' => '$actions.click.pixel.z2.count' ],
'z3pc' => [ '$sum' => '$actions.click.pixel.z3.count' ],
'z1ac' => [ '$sum' => '$actions.click.apiOnly.z1.count' ],
'z2ac' => [ '$sum' => '$actions.click.apiOnly.z2.count' ],
'z3ac' => [ '$sum' => '$actions.click.apiOnly.z3.count' ],
'z1sc' => [ '$sum' => '$actions.click.s2s.z1.count' ],
'z2sc' => [ '$sum' => '$actions.click.s2s.z2.count' ],
'z3sc' => [ '$sum' => '$actions.click.s2s.z3.count' ],
//impressions
'z1ii' => [ '$sum' => '$actions.display.import.z1.count' ],
'z2ii' => [ '$sum' => '$actions.display.import.z2.count' ],
'z3ii' => [ '$sum' => '$actions.display.import.z3.count' ],
'z1pi' => [ '$sum' => '$actions.display.pixel.z1.count' ],
'z2pi' => [ '$sum' => '$actions.display.pixel.z2.count' ],
'z3pi' => [ '$sum' => '$actions.display.pixel.z3.count' ],
'z1ai' => [ '$sum' => '$actions.display.apiOnly.z1.count' ],
'z2ai' => [ '$sum' => '$actions.display.apiOnly.z2.count' ],
'z3ai' => [ '$sum' => '$actions.display.apiOnly.z3.count' ],
'z1si' => [ '$sum' => '$actions.display.s2s.z1.count' ],
'z2si' => [ '$sum' => '$actions.display.s2s.z2.count' ],
'z3si' => [ '$sum' => '$actions.display.s2s.z3.count' ],
]
], [
'$project' => [
'impressions' => [ '$add' => ['$z1ii', '$z2ii', '$z3ii',
'$z1pi', '$z2pi', '$z3pi',
'$z1ai', '$z2ai', '$z3ai',
'$z1si', '$z2si', '$z3si'] ],
'clicks' => [ '$add' => ['$z1ic', '$z2ic', '$z3ic',
'$z1pc', '$z2pc', '$z3pc',
'$z1ac', '$z2ac', '$z3ac',
'$z1sc', '$z2sc', '$z3sc'] ],
'importSales' => [ '$add' => ['$z1is', '$z2is', '$z3is'] ],
'pixelSales' => [ '$add' => ['$z1ps', '$z2ps', '$z3ps'] ],
'apiSales' => [ '$add' => ['$z1as', '$z2as', '$z3as'] ],
's2sSales' => [ '$add' => ['$z1ss', '$z2ss', '$z3ss'] ],
]
]
];
//do something with this
$options = [ 'timeout' => -1 ];
$result = $summaryDB->command(
[
'aggregate' => $summaryCollection,
'pipeline' => $pipeline,
],
$options
);
var_dump($result);
When you run DB command, the first argument is the name of the command as the key and the value is the name of the collection.
In your case you should be passing "hitSummary" as the value of 'aggregate' and not the collection object.
See simple command example here: http://php.net/manual/en/mongodb.command.php