How to convert below MongoDB query into PHP? - php

Below query worked fine in Studio 3T and Robomongo, But I want to convert it into PHP format,
Following is my query,
db.news.aggregate([
{
$match: { "_id" : "1" }
},
{
"$project": {
"comments": {
"$filter": {
"input": "$comments",
"as": "comment",
"cond": { "$eq": [ "$$comment.status", "active" ] }
}
}
}
}, {
"$project": {
"comments": {
"$slice": [
{
"$slice": [
"$comments",
{
"$subtract": [ { "$size": [ "$comments" ] }, 1 ]
}
]
}, -1
]
}
}
}])
I have tried below, But it giving error "Error: localhost:27017: FieldPath field names may not be empty strings."
PHP converted sample:
<?php
$commentsAggregate=array(
array('$match' => array("_id" => "1")),
array('$project' => array(
"comments" => array(
'$filter' => array(
"input" => "$comments",
"as" => "comment",
"cond" => array('$eq' => array( "$$comment.status", 'active'))
)))),
array('$project' => array(
"comments" => array(
'$slice' => array(array(
'$slice' => array("$comments",array('$subtract' => array( array( '$size' => array("$comments")),1)))
), -1)
)))
);
$cursor=$collectionNews->aggregate($commentsAggregate);
Please help me to convert above query.

The error message "FieldPath field names may not be empty strings" originates from the server. Looking at the example PHP code you've provided, I notice that you're inconsistently using single- and double-quoted strings. In particular, these two strings stand out:
"$$comment.status"
"$comment"
PHP is evaluating variable references inside double-quoted strings. Assuming the local scope does not actually have a $comment variable defined, those strings are going to resolve to "$.status" and "", respectively. As evidenced in this script and execution output on 3v4l.org, those examples should at least result in a PHP notice for an undefined variable (my local PHP configuration happens to report this at the "error" level). If you have no record of that error message, I would suggest the following:
Check your error_reporting configuration.
Ideally, you should report everything (E_ALL) in a development environment. Full reporting is also advisable for production, although there you would likely want to disable display_errors (for security) and instead ensure everything is logged properly.
If it turns out the error was logged, look into how it was missed while debugging this issue.
As for fixing the root cause, you should be mindful to use single-quoted strings when writing MongoDB queries/commands in PHP. There is a note about this in the MongoCollection::find() documentation, but it's not something we repeat on every page, as PHP's double-quoted string evaluation is outside the control of the driver.

Related

Malformed UTF-8 characters, possibly incorrectly encoded Laravel

Laravel 8
I have seen a few of these questions, but the answers are either msising, not for php, or some weird hack.
I have a table in the database, mariadb, with the field type of LONGTEXT - equates to JSON field.
in my model I do:
protected $casts = [
'event_data' => 'array',
];
public function setEventDataAttribute($value) {
$this->attributes['event_data'] = json_encode($value);
}
The data going into the field is:
array:12 [
"start" => "2022-08-23T00:00:00+00:00"
"end" => "2022-08-23T00:00:00+00:00"
"all_day" => false
"unassigned" => true
"draft" => true
"title" => "ggggg"
"notes" => "test"
"active" => true
"schedule_calendar_id" => null
"jobcode_id" => 122723308
"customfields" => array:2 [
1782352 => "Dirty"
1782354 => "Vacant"
]
"color" => "#888888"
]
When I run json_encode($value) where $value is the above array, I get:
{
"start": "2022-08-23T00:00:00+00:00",
"end": "2022-08-23T00:00:00+00:00",
"all_day": false,
"unassigned": true,
"draft": true,
"title": "ggggg",
"notes": "test",
"active": true,
"schedule_calendar_id": null,
"jobcode_id": 122723308,
"customfields": {
"1782352": "Dirty",
"1782354": "Vacant"
},
"color": "#888888"
}
which according to every validator out there, this is valid JSON. How ever attempting to set this as the attribute into the field throws:
Malformed UTF-8 characters, possibly incorrectly encoded
I can, above the $this->attributes['event_data'] do:
dump(json_encode($value), json_decode(json_encode($value)));
And get the json object listed above and get a stdClass class object of the decoded json.
So my question is:
If the online JSON formatters are saying this is valid JSON, php has no issue encoding and decoding it - why can't laravel insert it? Is it the dates? they must be in ISO8601 Format.
What is going on? I have done this, json encoding like this, a thousand times with no issue.

Override/Update Variable/Array in php file

In my recent project, working on console command where I need to perform/run various action mentioned in json based on the linux standard convention as
what:mv(Move),type:file,dir
what:mkdir(Make Directory)
what:touch(Make File)
what:cp(Copy), type:file,dir
what:echo (Write into File), type:override,append
what:sed (Find and Replace in file)
and param schema would be same almost exact to linux convention.
Current SetUp (Mkdir, touch)
Json Schema (Array)
"actions" => [
[
'what' => "mkdir",
'param' => [
'name' => "cache",
'in' => "bootstrap",
],
],
[
'what' => "touch",
'param' => [
'name' => ".gitignore",
'in' => "bootstrap/cache",
],
]
],
and its iterate through all action and resolve action class per what type (mkdir,touch) like MkdirOperation for mkdir and call handle functions respectively.
<?php
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
class MkdirOperation extends Operation
{
const ATTR_IN = "in";
const ATTR_NAME = "name";
public function handle()
{
$path = $this->_path();
$this->oIO->comment($path);
if ($this->oFileSystem->isAbsolutePath($path)) {
try {
$this->oFileSystem->mkdir($path);
} catch (IOExceptionInterface $e) {
echo "An error occurred while creating your directory at "
.$e->getPath();
}
$this->oIO->info("Directory created at:".$path);
}
}
private function _path()
{
return $this->oConfig->getBaseDir()
.$this->aParam[self::ATTR_IN].DIRECTORY_SEPARATOR
.$this->aParam[self::ATTR_NAME]
.DIRECTORY_SEPARATOR;
}
}
Requirement:
//somefile.php
$path = "/var/www/ins/"
//someotherfile.php
return [
'files' = [
'Path\\To\\NameSpace',
'Path\\To\\NameSpace'
]
];
So, basically I want to update/override my mentioned variable/array according to specific rules, for that purpose, I tried to prepare rules in json schema:
"actions": [
{
"what": "sed",
"in": "path/to/somefile.php",
"find": {
"type": "variable",
"value": "path"
},
"replace": {
"type": "variable",
"value": "__DIR__.'/../vendor/compiled.php';"
}
},{
"what": "put",
"value": "Path\\To\\NameSpace",
"in": "path/to/someotherfile.php",
"find": {
"type": "array",
"at": "files"
}
}
]
The Component I'm using
symfony/console
symfony/finder
Symfony/filesystem
Looking for:
Suggestion to organize rules set schema in such manner to iterate through all actions for update/override variable or push/pull element from array and perform action.
Mechanism to update the value of specific variable and also push/pull element from array/subarray using php.
If still something unclear from my side let me know.
Thanks in advance.

Correct params for ElasticSearch with PHP

I am attempting to make a Google like search using ElasticSearch and PHP. I have been reading a ElasticSearch book and I think I was to use simple_query_string query type that can take the keywords (or phrase) from a search box and try to find some of all of the terms entered.
I am using the PHP ElasticSearch library in my project and after connecting to my server I am trying to pass a $client->search($params) to my search to return a result.
I have this as my params array
$params =
[
'index' => 'letsmeetup',
'type' => 'person',
'body' =>
[
'query' =>
[
'simple_query_string' =>
[
'query' => $keywords,
'fields' => [
"first_name","last_name","bio","username","email_address","interests","skills"
]
]
]
]
];
I used a phrase like 'People who love php' and I get results. I tried 'real time web' (which is in my bio) as I get the correct result.
Problem is when I try 'Er', knowing there is a first_name of "Erin", or 'Neo', which I have "neo4j" in my bio, it's returning no results. Do I have the params array correct?
You need to use wildcards for these kind of queries
{
"query": {
"query_string": {
"fields": [ "first_name","last_name","bio","username","email_address","interests","skills"],
"query": "Er*"
}
}
}
This will match "Erin", "Eric", "Error" and so on.
You can find more information about Query String Syntax and wildcards here. https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax
I hope this helps!

elasticsearch php search exists

How might one do the following request
GET /giata_index/giata_type/_search/exists
{
"query": {
"bool": {
"must": [
{
"term": {
"status": 2
}
},
{
"term": {
"ids": "26744"
}
}
]
}
}
}
with ElasticSearch's PHP library?
I have played around with the exists endpoint, but as it turns out, that can only check whether a specific uid is existant or not. So I guess I need to do a search. But I can't find a parameter in the Search endpoints's whitelist that would allow a simple check for exists or not.
The reason why I would like to avoid getting the entire document and just ask whether it exists or not is because I have multiple hundreds of thousands of imports and just as many documents in ES, so I would like it to put as little work into it as possible.
Note: I have also looked into head requests that are possible via HTTP requests (only retrieve the header of a document - either 200 or 404). But that would probably only exist for requests via HTTP.
If worse comes to worse I could shoot a curl via php and simply do it via HTTP. But I would prefer it otherwise.
It seems indeed that there's no endpoint voor search exists, but I think you use a simple alternative:
Use an empty "fields" array. And count the results of your query. If == 0: false. If > 0: true
GET /giata_index/giata_type/_search
{
"fields": [],
"query": {
"bool": {
"must": [
{
"term": {
"status": 2
}
},
{
"term": {
"ids": "26744"
}
}
]
}
}
}
An other alternative is to use _count : https://www.elastic.co/guide/en/elasticsearch/reference/1.6/search-count.html
It should be possible with the latest 2.x version.
Code sample could be something like this:
$clientBuilder = Elasticsearch\ClientBuilder::create();
// Additional client options, hosts, etc.
$client = $clientBuilder->build();
$index = 'your_index';
$type = 'your_type';
$params = [
'index' => $index,
'type' => $type,
'body' => [
'query' => [
'bool' => [
'must' => [
[
'term' => [
"status" => 2
]
],
[
'term' => [
'ids' => "26744"
]
]
]
]
]
];
try {
$client->searchExists($params);
} catch (Exception $e) {
// Not found. You might want to return FALSE if wrapped in a function.
// return FALSE;
}
// Found.
It is worth noting that if search is not wrapped in try/catch block it can break execution and throw an exception (status code 4xx if not found).
Also, it can not be used effectively in future mode.

How to set OR condition in Phalcon PHP ORM?

I using Phalcon PHP as PHP MVC Framework with MongoDB.
I can find object according with some criteria:
$user = User::findFirst(array(array('username' => $login, 'email'=> $login)));
As you can note, this request will return me the record according logical AND operator between conditions. I need to form request that will return result according with OR operator between conditions.
The problem also is that I'm using MongoDB, so, as I can suppose, I can't write PHQL request manually.
Just a matter of mangling PHP arrays
$user = User::findFirst( array(
'$or' => array(
array( 'username' => $login),
array( 'email' => $login)
)
));
So not only do I show the answer but also how my totals non PHP mind solves this problem:
$result = '{ "$or": [ { "username": "login" }, { "email": "login" } ] }';
echo var_dump( json_decode( $result ) );
$test = array(
'$or' => array(
array( 'username' => 'login'), array( 'email' => 'login')
)
);
echo json_encode( $test ) ."\n"
So in just a few lines we converted and proved. So since you knew the JSON from either the manual page or reading another question on SO, just convert it. And it's one of the reasons I submit the valid JSON in responses here, is so that the logic can be translated into just about any language implementation.
You can pass column names as string in first param:
$user = User::findFirst('username = "'.$login.'" OR email = "'.$login.'"');
$result = '{ "$or": [ { "username": "login" }, { "email": "login" } ] }';
User::findFirst(array(json_decode($query,true)));
$result is the exact json which can be used to trigger queries in mongodb command line
json_decode with 2nd parameter true will output the array style format of JSON

Categories