I have created query in mongoDB. In MongoChef this query produces more than 10 thousand records in less than 2 seconds. Now I want to execute this query in PHP.
So i don't know how to write query in php as I read various documents on internet but confused how to implement it.
db.PMS.aggregate(
[
{$project:
{EventTS:1,MainsPower:1,PanelID:1}
},
{$unwind:
{path:"$MainsPower",includeArrayIndex:"arrayIndex",preserveNullAndEmptyArrays:true}
},
{ $match: { "MainsPower":{$ne:null}}},
{ $match: { "EventTS":{$gt:new Date("2016-01-01")}}},
{$project:
{MainsPower:1,
PanelID:1,
timestamp:{"$add":
[{'$subtract' : ["$EventTS",new Date("1970-01-01")]},
{"$multiply":[60000,"$arrayIndex"]}
]}
}
}
]
);
You can use some resources available on the php official documentation. A mapping of sql queries in php to mongoDB queries in php can be found here.
Also I have a demo login and registration script at my github. You can view those in this repo.
If you use MongoDB PHP Library you should be able to do something similar to this:
$mongo = new MongoClient();
$database = $mongo->examples;
$collection = $database->PMS;
$pipeline = [
[
'$project' => [
'EventTS' => 1,
'MainsPower' => 1,
'PanelID' => 1,
]
],
[
'$unwind' => [
'path' => '$MainsPower',
'includeArrayIndex' => 'arrayIndex',
'preserveNullAndEmptyArrays' => true
]
],
...
];
$cursor = $collection->aggregate($pipeline);
Related
I'm using elasticsearch version 8.4 with PHP. I created the index articles e and he has all the registers that are present in the correspondent table in database.
I need to do a search with elasticsearch that return the same results that a SQL search would do.
SELECT *
FROM articles
WHERE title LIKE '%Document%'
However, the results are not the same using elasticsearch php. The php code follows:
<?php
require_once "vendor/autoload.php";
use Elastic\Elasticsearch\ClientBuilder;
$client = ClientBuilder::create()
->setHosts(['localhost:9200'])
->setBasicAuthentication('elastic','secret')
->build();
$params = [
'index' => 'articles',
'from' => 0,
'size' => 5000,
'body' => [
'query' => [
'match' => [
'title' => 'Document'
]
]
]
];
if (!empty($results['hits']['hits']))
{
echo "<pre>";
print_r($results['hits']['hits']);
echo "</pre>";
}
I tried 'wildcards' and 'regexp' instead of 'match', but it not worked.
I read these pages of docs to help in this case:
https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-like-rlike-operators.html#sql-like-operator https://www.elastic.co/guide/en/elasticsearch/client/php-api/8.4/search_operations.html
Is there any to reproduce this elasticsearch php code return same results of sql query executed directly in database?
We started our web-based app back in 2012 when Perl was still popular. Now we want to reimplement it in PHP, preferably Laravel. However, I miss the power of DBIx::Class in their default ORM, Eloquent, and the alternative, Doctrine, from reading the docs seems more complicated, but doesn't solve the issue either. What I use DBIx::Class for:
Regenerate model classes from reading the DB structure, preserving any code that has been added to them (should have).
Generate complex queries (incl. nested joins, subqueries) from pure language constructs, no SQL needed (must have).
Code sample:
rows => $rows,
page => $page,
'select' => [
'entity_id',
{ group_concat => [ { distinct => 'pictures.id' } ], -as => 'photos' },
{ '' => [ 'entity.name' ], -as => 'entity_name' },
{ '' => [ 'municipality.name' ], -as => 'municipality_name' },
{ '' => [ 'me.birth_date' ], -as => 'bd' },
{ concat => [ { date_format => [ 'me.birth_date', \$c->config->{dateFormat} ] }, \"' ('", { timestampdiff => [ \'YEAR', 'me.birth_date', \'CURDATE()' ] }, \"')'" ], -as
{ date_format => [ 'me.birth_date', \$c->config->{dateFormat} ], -as => 'bd1' },
{ timestampdiff => [ \'YEAR', 'me.birth_date', \'CURDATE()' ], -as => 'bd2' },
{ '' => [ 'entity_state_type.name' ], -as => 'entity_state_name' },
{ '' => [ 'data_list_item.name' ], -as => 'entity_state_reason_name' },
{ '' => [ 'entity_state.note_text' ], -as => 'entity_state_note' },
{ '' => [ { if => [ 'entity.archived', \"'Yes'", \"''" ] } ], -as => 'entity_archived' },
],
join => {
entity => [ 'municipality', 'pictures', { 'entity_state' => [ 'entity_state_type', 'data_list_item' ] } ],
},
group_by => [ 'entity.id' ],
Subclass the result (row) and resultset classes to add user role-based limiting conditions transparently to the application code (must have, or equivalent).
The call and the resulting query:
$c->model('DB::Person')->all
SELECT * FROM person WHERE owner = <user_id>
...if the user role security settings indicate user should only access his own persons.
The security settings are read from DB on request start and specify which security conditions (separate classes) should apply to which table.
This moves all security away from application code, where mistakes are made most often.
Which PHP library would allow us to implement this?
I try to get some results filtered with a condition if data does not exist or if exists and is older than...
I have query build with PHP query builder
->addOr(
['interactions.lastDisplays' => ['$elemMatch' => [
'user' => new \MongoId($id),
'date' => ['$lte' => $date]
]]],
['interactions.lastDisplays.user' => ['$ne' => new \MongoId($id)]]
)
And it logs to:
db.Post.find({
"$or": [
{ "interactions.lastDisplays": {
"$elemMatch": { "user": ObjectId("5a61bb816e0bb1542a0bc574"),
"date": { "$lte": new ISODate("2019-06-14T13:22:01+00:00") } } } },
{ "interactions.lastDisplays.user": {
"$ne": ObjectId("5a61bb816e0bb1542a0bc574") }
}]
}).limit(25).skip(0);
For some reason, it does not return any results in PHP. When I copy it and run directly on a database it works fine, and all 25 results are returned.
The solution was as simple as changing $lte to MongoDate.
->addOr(
['interactions.lastDisplays' => ['$elemMatch' => [
'user' => new \MongoId($id),
'date' => ['$lte' => $new \MongoDate($date->getTimestamp())]
]]],
['interactions.lastDisplays.user' => ['$ne' => new \MongoId($id)]]
)
The strange thing that I don't understand yet is that it used to work with DateTime in other queries (but they don't have nested array conditions, so maybe it's the issue). And also that query log is pretty the same.
I'm currently working with the current PHP MongoDB\Driver .
I need to use an geoNear query to fetch points from my current location. The required 2dsphere index is already set, the query works in the console and delivers multiple results:
db.runCommand({geoNear: 'pois', near: [ 52.264633, 6.12485 ], spherical: true, maxDistance: 1000, distanceField: 'distance'})
Since the previous methods are deprecated, I can't use the old aggregate functions.
I'm now trying to find the right way to build the query I need with the current Query or Command classes.
What I've tried is the following:
$query = array(
'geoNear' => 'pois',
"near" => array(
52.264633,
6.12485
),
"spherical" => true,
"maxDistance" => 1000,
"distanceField" => "distance"
);
$cmd = new MongoDB\Driver\Command($query);
$returnCursor = $this->conn->executeCommand("database.pois", $cmd);
$arrReturn = $returnCursor->toArray();
return $arrReturn;
If I use this, I will return this Runtime Error:
"exception": [
{
"type": "MongoDB\\Driver\\Exception\\RuntimeException",
"code": 18,
"message": "Failed to decode document from the server."
}
]"
I couldn't find a solution for my case and also I couldn't find more information to this error.
If I change the Command up to a Query, the execution doesn't fail, but there are no results.
My mongodb is on the version 3.2, my PHP version is PHP Version 7.0.16-4+deb.sury.org~trusty+1 and the mongodb Exension is version 1.2.3
You can use the aggregate in the following way with new driver.
$pipeline = array(array(
'$geoNear'=> array(
'near' => array(
52.264633,
6.12485
),
'spherical' => true,
'maxDistance' => 1000,
'distanceField' => "distance"
)));
$cmd = new \MongoDB\Driver\Command([
'aggregate' => 'pois',
'pipeline' => $pipeline
]);
$returnCursor = $this->conn->executeCommand("database", $cmd);
$arrReturn = $returnCursor->toArray();
There is also a Library from Mongo that expands the default functionality of the driver to make it a little more user friendly
but as its not built into the php website its easy to miss
MongoDB\Collection::aggregate($pipeline, $options)
where
$pipeline = array(array(
'$geoNear'=> array(
'near' => array(
52.264633,
6.12485
),
'spherical' => true,
'maxDistance' => 1000,
'distanceField' => "distance"
)
));
We have created MongoDB query but it's not converted into PHP
MongoDB query
db.crawled_jobs.aggregate(
[
{
$geoNear: {
near: {
type: "Point",
coordinates: [-73.86, 41.07 ]
},
distanceField:"dist.calculated",
maxDistance: 100000,
includeLocs: "dist.location",
num: 1225,
spherical: true,
"query": { "title": /sales/ }
}
}
])
Mongodb query working fine and we get results
In php \MongoDB\Driver\Command
Create an array in PHP and use for MongoDB query
$queryString = [['$geoNear'=> ['near'=> [ 'type'=> "Point",'coordinates'=> [$lon,$lat] ], 'distanceField'=> "dist.calculated",'maxDistance'=> $maxDistance, 'includeLocs'=> "dist.location", 'num'=> 10000, 'spherical'=> true, 'query' => ['title' => '/sales/'] ] ] ];
after this query, MongoDB query look like this
db.crawled_jobs.aggregate([{"$geoNear":"near":"type":"Point","coordinates":[-73.86,41.07]},"distanceField":"dist.calculated","maxDistance":100000,"includeLocs":"dist.location","num":1225,"spherical":true,"query":{"title":"\/sales\/"}}}])
We didn't get result because it add backslash in query
"query":{"title":"\/sales\/"}
But we need like this "query": { "title": /sales/ }
Can anyone help us
\MongoDB\Driver\Command does not accept string :( it require the only array not string)
Fix it with this
'query' => ['title'=> array('$regex' => 'NYC')]
You need to use MongoDB\BSON\Regex class to generate regex as following:
'query' => ['title' => new MongoDB\BSON\Regex('sales')]