Use of "$or" condition is not working - php

I am developing a search portal, so I need to find the searched text on more than one field.
I am trying to use the advanced query of MongoDB in PHP.
My code is:
$mongo = new MongoDBCONN();
$jobCollection = $mongo->select('jobs', $mongo);
$advanceQuery=array('orgId' => '21')
$query_q=array('$or'=>array(
array("jobTitle"=>new MongoRegex("/$search/i")),
array("jobLocationCity"=>new MongoRegex("/$search/i")),
array('jobLocationCountry'=>new MongoRegex("/$search/i"))
));
$advanceQuery=array_merge($advanceQuery,$query_q);
$jobCollection->find($advanceQuery);
It returns NULL every time, whereas MongoRegex is working fine, because when I use it to search on only one field it works.
$search is post as input text.

I found the answer on my own, actually this was a version problem. I was using 1.4.4, but after update to 1.7.4 it is working. On the mongo website I found that the "or" operator was included only from version 1.7.x onwards.

$regexObj = new MongoRegex("/$search_term/i");
$where = array(
'$or' => array(
array("Name" => $regexObj),
array("image.caption.text" => $regexObj),
array("image.user.username" => $regexObj)
)
);
$cursor = $collection->find($where);
// Parsing the results
while ($cursor->hasNext())
{
$obj = $cursor->getNext();
$profile_image = $obj['image']['user']['profile_picture'];
}

If you need to combine the regex with another operator, you need to use the $regex clause. That one is missing in your code example. Please read again about how to query with regulars expressions.

Related

Add new field to a MongoDB document parsing from String to Int using updateMany

In my MongoDB collection, all documents contain a mileage field which currently is a string. Using PHP, I'd like to add a second field which contains the same content, but as an integer value. Questions like How to change the type of a field? contain custom MongoDB code which I don't want to run using PHP, and questions like mongodb php Strings to float values retrieve all documents and loop over them.
Is there any way to use \MongoDB\Operation\UpdateMany for this, as this would put all the work to the database level? I've already tried this for static values (like: add the same string to all documents), but struggle with getting the data to be inserted from the collection itself.
Some further hints:
I'm looking for a pure PHP solution that does not rely on any binary to be called using exec. This should avoid installing more packages than needed on the PHP server
Currently, I have to use MongoDB in v4.0. Yes, that's not the most recent version, but I'm not in the position to perform an upgrade
Try this, please:
01) MongoDB Aggregate reference:
db.collectionName.aggregate(
[
{ "$addFields": {
"intField": { "$toInt": "$stringFieldName" }
}},
{ "$out": "collectionName" }
]
)
02) Possible PHP solution (Using as reference https://www.php.net/manual/en/mongocollection.aggregate.php):
$pipeline = array(
array(
'$addFields' => array(
'integerField' => array('$toInt' => '$mileage')
)
),
array(
'$out' => 'collection'
),
);
$updateResult = $collection->aggregate(pipeline);
You could use $set like this in 4.2 which supports aggregation pipeline in update.
$set stage creates a mileageasint based on the previous with $toInt value
db.collection.updateMany(
<query>,
[{ $set: { "mileageasint":{"$toInt":"$mileage" }}}],
...
)
Php Solution ( Using example from here)
$updateResult = $collection->updateMany(
[],
[['$set' => [ 'mileageasint' => [ '$toInt' => '$mileage']]]]
);

How to parse function name with arguments in PHP?

I am building a module for my own PHP framework, so my question is very specific and special. It's difficult to explain my question so I will go ahead and show it on code below.
I have a little piece of PHP in a $code variable, it looks like this:
$code = "___echo(TODAY_IS, date('j.n.Y', time()), time());";
What I need is to parse this $code variable and I want to get this result:
$result = array(
'function_name' => "___echo",
'arguments' => array(
0 => "TODAY_IS",
1 => "date('j.n.Y', time())",
2 => "time()"
)
);
I am thinking and I have tried using some regex, but neither worked sufficiently well. I also tried using Tokenizer, however I wasn't successful either.
Thanks for any hints or help in advance.
Here is a shot using PHP-Parser. It's likely going to be more useful than tokenizer or some freaky regex.
Example:
$code = "___echo(TODAY_IS, date('j.n.Y', time()), time());";
$parser = new PhpParser\Parser(new PhpParser\Lexer);
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
$statements = $parser->parse("<?php $code");
$result['function_name'] = $statements[0]->name->toString();
foreach ($statements[0]->args as $arg) {
$result['arguments'][] = $prettyPrinter->prettyPrint(array($arg));
}
var_export($result);
Output:
array (
'function_name' => '___echo',
'arguments' =>
array (
0 => 'TODAY_IS',
1 => 'date(\'j.n.Y\', time())',
2 => 'time()',
),
)
token_get_all() function is what you need here:
token_get_all("<?php ___echo(TODAY_IS, date('j.n.Y', time()), time());")
This returns a list of tokens parsed from the given string. See the tokens documentation for recognizing the items of the list.
In my opinion, tokenizer-based solution should be preferred over any regular expressions based on whatever is written in the PHP manual regarding syntax.

Text command will be removed > should use $text query instead

I've just set up MongoDB with last release of every components:
MongoDB 2.6.2
PHP 5.5.11 VC11
php_mongo.dll (I'm on windows) 1.4.3 ts VC11
I made a quick test to check if my DB is ok and I can retrieve my data using full text search:
$m = new MongoClient();
$db = $m->mytestdb;
$result = $db->command(
array(
'text' => 'items',
'search' => 'something',
'limit' => 50,
)
);
Everything is OK but when I see MongoDB logs there is one strange message I can't find any answers on the web:
[conn1] The text command will be removed in a future release. Use the $text query operator instead.
As I'm just starting to work on it it's kinda freaking me to know that the Full Text search I'm just using will be deprecated.
Even the official doc is using that code (see example #4).
So what should I use instead of my code? I'm afraid that if I use this code someday during an apt-get update & upgrade all my code will drop down.
I found out with the new $text from 2.6, here is how to do the same request as before with command:
$m = new MongoClient();
$db = $m->mytestdb;
$collection = $db->items;
$cursor = $collection->find(
array(
'$text' => array('$search' => 'something to search')
),
array (
'score' => array('$meta' => "textScore")
)
);
It seem's like they are rolling out $text in 2.6, and deprecating the text search feature.
you can reference more information of $text here.
http://docs.mongodb.org/manual/reference/operator/query/text/#op._S_text

Elasticsearch boosting syntax PHP

I did read the elasticsearch documentation but it lacks examples, for me.
I have put some documents in the es-engine, they contain the field "text" and "title".
Now I want to boost up the hits in the field "title". I'm using the php-api.
I tried this one:
$params_ci['index'] = 'all';
$params_ci['type'] = 'all';
$params_ci['body']['query']['query_string']['query'] = $query;
$params_ci['body']['function_score']['functions']['field_value_factor'] = array('field' => 'title',
'factor' => 1.2)
$client = ElasticClientFactory::build();
$client->search($params_ci)
But I get an error. Without the "function_score" it works.
... Parse Failure [No parser for element [function_score] ...
The biggest problem for me is how to translate the JSON in the documentation into the right place as arrays. I know JSON is like an array but often it fits not in my hierarchy of array?
Uses ElasticSearch Version: elasticsearch-1.1.1
The right synax is:
$params_ci['body']['query']['function_score']['functions']['field_value_factor'] = array('field' => 'title', 'factor' => 1.2)

MongoDB search $in _id php

Usually when I search for one related ID I do it like this:
$thisSearch = $collection->find(array(
'relatedMongoID' => new MongoId($mongoIDfromSomewhereElse)
));
How would I do it if I wanted to do something like this:
$mongoIdArray = array($mongoIDfromSomewhereElseOne, $mongoIDfromSomewhereElseTwo, $mongoIDfromSomewhereElseThree);
$thisSearch = $collection->find(array(
'relatedMongoID' => array( '$in' => new MongoId(mongoIdArray)
)));
I've tried it with and without the new MongoId(), i've even tried this with no luck.
foreach($mongoIdArray as $seprateIds){
$newMongoString .= new MongoId($seprateIds).', ';
}
$mongoIdArray = explode(',', $newMongoString).'0';
how do I search '$in' "_id" when you need to have the new MongoID() ran on each _id?
Hmm your rtying to do it the SQL way:
foreach($mongoIdArray as $seprateIds){
$newMongoString .= new MongoId($seprateIds).', ';
}
$mongoIdArray = explode(',', $newMongoString).'0';
Instead try:
$_ids = array();
foreach($mongoIdArray as $seprateIds){
$_ids[] = $serprateIds instanceof MongoId ? $seprateIds : new MongoId($seprateIds);
}
$thisSearch = $collection->find(array(
'relatedMongoID' => array( '$in' => $_ids)
));
That should produce a list of ObjectIds that can be used to search that field - relatedMongoID.
This is what I am doing
Basically, as shown in the documentation ( https://docs.mongodb.org/v3.0/reference/operator/query/in/ ) the $in operator for MongoDB in fact takes an array so you need to replicate this structure in PHP since the PHP driver is a 1-1 with the documentation on most fronts (except in some areas where you need to use an additional object, for example: MongoRegex)
Now, all _ids in MongoDB are in fact ObjectIds (unless you changed your structure) so what you need to do to complete this query is make an array of ObjectIds. The ObjectId in PHP is MongoId ( http://php.net/manual/en/class.mongoid.php )
So you need to make an array of MongoIds.
First, I walk through the array (could be done with array_walk) changing the values of each array element to a MongoId with the old value encapsulated in that object:
foreach($mongoIdArray as $seprateIds){
$_ids[] = $serprateIds instanceof MongoId ? $seprateIds : new MongoId($seprateIds);
}
I use a ternary operator here to see if the value is already a MongoId encapsulated value, and if not encapsulate it.
Then I add this new array to the query object to form the $in query array as shown in the main MongoDB documentation:
$thisSearch = $collection->find(array(
'relatedMongoID' => array( '$in' => $_ids)
));
So now when the query is sent to the server it forms a structure similar to:
{relatedMongoId: {$in: [ObjectId(''), ObjectId('')]}}
Which will return results.
Well... I came across the same issue and the solution might not be relevant anymore since the API might have changed. I solved this one with:
$ids = [
new \MongoDB\BSON\ObjectId('5ae0cc7bf3dd2b8bad1f71e2'),
new \MongoDB\BSON\ObjectId('5ae0cc7cf3dd2b8bae5aaf33'),
];
$collection->find([
'_id' => ['$in' => $_ids],
]);

Categories