How to convert mongoDB query into PHP? - php

My query is working in mongodb and produce output Properly. But same query i tried to run using php then it gives following error
Array
(
[ok] => 0
[errmsg] => A pipeline stage specification object must contain exactly one field.
[code] => 16435
)
Following is my MongoDB Query
db.sample_coll.aggregate(
{
$unwind: {
path:"$KeyValues",
includeArrayIndex:"arrayIndex",
preserveNullAndEmptyArrays:true
}
},
{
$project: {
timestamp:{
"$add":["$EventTS",{"$multiply":[60000,"$arrayIndex"]}]
} ,
"InputVolt":"$KeyValues.InputVolt",
arrayIndex:1
}
},
{
$match: {
$and: [
{InputVolt: {$ne: null}}
]
}
}
);
The Above query is converted in php
$pipeline = array(
array('$unwind' =>
array( 'path' => '$KeyValues'),
array( 'includeArrayIndex' => 'arrayIndex' ),
array( 'preserveNullAndEmptyArrays' => 'true' )
),
array(
'$project' => array(
'timestamp' => array(
'$add' => array(
'$EventTS',
array('$multiply' => array( 60000, '$arrayIndex' ))
)
),
array( 'InputVolt' => array( '$KeyValues', 'InputVolt' ) ) ,
array('arrayIndex' => 1)
)
),
array(
'$match' => array(
'$and' => array(
array('InputVolt' => array('$ne' => null )),
)
)
)
);
$result = $collection->aggregate($pipeline);
Kindly help to resolve this issue.
Thanks in advance

Your pipeline in PHP:
$pipeline = array(
array('$unwind' => array(
'path' => '$KeyValues',
'includeArrayIndex' => 'arrayIndex',
'preserveNullAndEmptyArrays' => true
)),
array('$project' => array(
'timestamp' => array(
'$add' => array('$EventTS', array('$multiply' => array(60000, '$arrayIndex')))
),
'InputVolt' => '$KeyValues.InputVolt',
'arrayIndex' => 1
)),
array('$match' => array(
'InputVolt' => array('$ne' => null)
))
);

Related

mongodb with PHP driver aggregate(find) with multiple $match $or $and condition

hi i have a problom with mongo $aggregate on the php driver
i have this code in PHP:
$match1 = array( '$and' => array(
array("uid" => array('$nin'=> $where_blocked)),
array("type" => "picture" ),
array("active" => true )
));
$match2 = array( '$and' => array(
array("uid" => array('$in'=> $where)),
array("type" => "users" )
));
$query = array(
array(
'$match' => array(
'$or' => array( $match1,$match2 )
),
),
array(
'$lookup' => array(
'from' => 'users',
'localField' => 'objId',
'foreignField' => '_id',
'as' => 'user'
),
),
array(
'$lookup' => array(
'from' => 'pictures',
'localField' => 'objId',
'foreignField' => '_id',
'as' => 'pic'
),
),
array(
'$limit' => $pageSize
),
array(
'$sort' => array("DateCreated" => -1 )
),
array(
'$skip' => $pageSize*($page-1)
)
);
$cursor = $log->aggregate($query);
this is working but i only get the $match1 not the $match2 i need to get OR match 1 or match2 depending of the most new document.
on find this wil work:
$query_or = array('$or' => array($match1,$match2));
$cursor = $log->find($query_or)->sort(array("DateCreated" => -1))->skip($pageSize*($page-1))->limit($pageSize);
but need the $lookup (join) and i can not use it on find
can someone help me?
Thanks
If you absolutely need to use $lookup, just use aggregate instead of find.
It does work and will bring you all the data:
db.your_table.aggregate([
{
$match: {
$or: [
{type:"picture"},
{type:"rate"}
]
}
},
{
$lookup: {
'from' : 'users',
'localField' : 'objId',
'foreignField' : '_id',
'as' :'user'
}
},
{
$lookup: {
'from' : 'pictures',
'localField' : 'objId',
'foreignField' : '_id',
'as': 'pic'
}
}
])

How do I group by on a dbref in MongoDB with Doctrine

I want to do an aggregation query where I can group by a dbref. This is what I've tried.
$aggregation = array(
array(
'$group' => array(
'_id' => '$foreign.$id',
'doc' => array(
'$last' => '$$ROOT'
)
)
),
array(
'$sort' => array(
'date' => -1
)
)
);
return $this->getDocumentManager()->getDocumentCollection('AppBundle:Collection')->aggregate($aggregation)->toArray();
But this attempt fails because you're not allowed to use the second $ sign in '$foreign.$id'. How can I do this query?
After a lot of searching I've found this Bug Ticket on the monogdb Jira which deals with basically this / an similar issue.
The last comment on this ticket offers an workaround to resolve the issue as an command line code. I've taken this solution and built it into an aggregation query which solved my problem.
$aggregation = array(
array(
'$addFields' => array(
'foreignId' => array(
'$arrayToObject' => array(
'$map' => array(
'input' => array(
'$objectToArray' => '$foreign'
),
'in' => array(
'k' => array(
'$cond' => array(
array(
'$eq' => array(
array(
'$substrCP' => array(
'$$this.k', 0, 1
)
),
array(
'$literal' => '$'
)
)
),
array(
'$substrCP' => array(
'$$this.k',1,['$strLenCP' => '$$this.k']
)
),
'$$this.k'
)
),
'v' => '$$this.v'
)
)
)
)
)
),
array(
'$group' => array(
'_id' => '$foreignId',
'doc' => array(
'$last' => '$$ROOT'
)
)
),
array(
'$sort' => array(
'date' => -1
)
)
);
$this->getDocumentManager()->getDocumentCollection('AppBundle:Collection')->aggregate($aggregation)->toArray();
This query gives me the correct and expected result.

Can’t filter search result

My Elasticsearch query is like that:
array(
'index' => 'myindex',
'type' => 'myindextype',
'from' => 0,
'size' => 500,
'body' => array(
'query' => array(
'filtered' => array(
'filter' => NULL,
'query' => array(
'query_string' => array(
'default_operator' => 'AND',
'query' => 'atm*',
'minimum_should_match' => '80%',
'default_field' => 'index'
)
)
)
)
)
);
Result is like that:
array(
'took' => 6,
'timed_out' => false,
'_shards' => array(
'total' => 5,
'successful' => 5,
'failed' => 0
),
'hits' => array(
'total' => 492,
'max_score' => 1,
'hits' => array(
0 => array(
'_index' => 'myindex',
'_type' => 'myindextype',
'_id' => 'Branch-571',
'_score' => 1,
'_source' => array(
'indexId' => 'Branch-571',
'objId' => '571',
'index' => 'atm Baki CNaxcivanski lisey Baki sheh Zig shossesi Admiral Naximov kuc 1 ',
'type' => 'Branch',
'title' => 'Bakı C.Naxçıvanski lisey'
)
),
.................................................................................................
196 => array(
'_index' => 'myindex',
'_type' => 'myindextype',
'_id' => 'Page-114',
'_score' => 1,
'_source' => array(
'indexId' => 'Page-114',
'objId' => 'Page-114',
'index' => 'atm Baki CNaxcivanski lisey Baki sheh Zig shossesi Admiral Naximov kuc 1 ',
'type' => 'Page',
'title' => 'Kreditlər'
)
)
.................................................................................................
)
)
);
I want to filter result and get results where 'type' => 'Branch' and I change query like that
array(
'index' => 'myindex',
'type' => 'myindextype',
'from' => 0,
'size' => 10,
'body' => array(
'query' => array(
'filtered' => array(
'filter' => array(
'bool' => array(
'must' => array(
'term' => array(
'type' => 'Branch'
)
)
)
),
'query' => array(
'query_string' => array(
'default_operator' => 'AND',
'query' => 'atm*',
'minimum_should_match' => '80%',
'default_field' => 'index'
)
)
)
)
)
);
But this search return nothing.
array(
'took' => 2,
'timed_out' => false,
'_shards' => array(
'total' => 5,
'successful' => 5,
'failed' => 0
),
'hits' => array(
'total' => 0,
'max_score' => NULL,
'hits' => array()
)
);
I think query is right but no idea why it didn't get any result.
Mapping is
array(
'myindex' => array(
'mappings' => array(
'myindextype' => array(
'properties' => array(
'index' => array(
'type' => 'string'
),
'indexId' => array(
'type' => 'string'
),
'objId' => array(
'type' => 'string'
),
'title' => array(
'type' => 'string'
),
'type' => array(
'type' => 'string'
)
)
)
)
)
)
I have find answer myself. The search query must be like that
POST _search
{
"query": {
"bool" : {
"must" : {
"query_string" :{
"query":"atm*",
"default_operator":"AND",
"minimum_should_match":"80%",
"default_field":"index"
}
},
"filter": {
"term": {
"type.keyword": "Branch"
}
}
}
}
}
All is working good now.

Elasticsearch range filter not working (No filter registered for)

I'm trying ta add a range filter to my search (only articles with workflow status <= 5 should appear) and getting errors
what's wrong with my range?
$searchParams = array(
'index' => $config->search->index,
'type' => 'xxxxxxxxxx',
'size' => 10,
'from' => ($page - 1) * 10,
'body' => array(
'query' => array(
'filtered' => array(
'query' => array(
'multi_match' => array(
'query' => $query,
'fields' => array('title^8', 'caption^5', 'teasertext^4', 'articletext^2') // ^x = Gewichtung des Felds
),
),
'filter' => array(
'bool' => array(
'must' => array(
'term' => array(
'deleted' => 0,
'visible' => 1
),
'range' => array(
'workflow_status' => array('lte' => '5')
)
)
)
)
)
)
),
'sort' => array('_score', '_id:desc')
here my mapping for status:
"workflow_status": {
"type": "integer",
"index": "not_analyzed"
}
What you have is not a valid Query DSL , must should take in an array.
The body should be something on these lines :
body =>
array(
'query' => array(
'filtered' => array(
'query' => array(
'multi_match' => array(
'query' => $query,
'fields' => array('title^8', 'caption^5', 'teasertext^4', 'articletext^2') // ^x = Gewichtung des Felds
),
),
'filter' => array(
'bool' => array(
'must' => array(
array(
'term' => array(
'deleted' => 0
)
),
array('term' => array(
'visible' => 1
)
),
array(
'range' => array(
'workflow_status' => array('lte' => '5')
)
)
)

Convert MongoDB console aggregate to php with array

i am failing to convert the following mongoDB console command:
db.customers.aggregate( [
{ $group : {
_id: {
year : { $year: "$since" },
month : { $month: "$since" }
},
count: { $sum: 1 }
}
}]
);
which works into php
$customers->aggregate(array(
'$group' => array(
'_id' => array( 'year' => array('$year' => '$since'),
'month' => array('$month' => '$since')
)
),
array(
'count' => array( '$sum' => 1 )
),
)
);
which returns exception: A pipeline stage specification object must contain exactly one field.
also already tried '"$since"' with no luck
The count field must be a part of the group.
$customers->aggregate(array(
'$group' => array(
'_id' => array( 'year' => array('$year' => '$since'),
'month' => array('$month' => '$since')
),
'count' => array( '$sum' => 1 )
)
));

Categories