I'm trying to match some input parameters in my API call using the newer Regex library in PHP, but it's not working so far. I'm using string interpolation to achieve this, but its returning any results. Here is my code:
$regex = new \MongoDB\BSON\Regex ("^{$this->device_id}:", 'i');
$pipeline = [
[
'$match' => [
'_id' => $regex,
]]
My document _id are of the type 'london_10:2016-10-05 09' which is the device_id:datehour.
When I var_dump the (string)$regex I get the following, which appears to be working:
string(15) "/^london_10:/i"
The issue is that when adding this to the pipeline, it returns an empty collection. I have equivalent code which is confirmed working but written in Python, and I need to rewrite it in PHP:
pipeline = [
{
'$match': {
"_id": re.compile("^%s:" %(self.device_id) )
}
}
]
The original code in the question is actually correct - I found that the problem wasn't in this part of my pipeline, but further downstream.
Related
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']]]]
);
I have the following mongo document structure
"search": [
[
"keyword",
"match"
],
[
"testing",
"something",
"serious"
]
]
I want to find documents where the array of keywords inside of the array match an $all query.
E.g if search had only 1 level I would do
{'search': {'$all': ['keyword','match']}}
I've tried using:
{'search': {'$elemMatch': {'$all': ['keyword','match']}}}
But I get no results.
If you know the array of keywords in advance and you want to match a document that contains that array inside the search array, you can just use a simple query as follows.
db.collection.find({"search": ["keyword", "match"]});
That should return your sample document. On the other hand, if the array is not completely contained by an element inside search, it will not return anything. For example the following query will not return your sample document.
db.collection.find({"search": ["keyword", "match", "testing"]});
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)
I am building a simple messaging system, and i have a collection in mongodb with documents like this:
{ "_id" : ObjectId("50ad003f9811e5bc5c000000"), "between" : [ "user1,user2,user3" ] }
I want to perform this query:
db.conversations.find({'between': ["user1,user2,user3"]});
to get this exact document back. This query works in mongo shell.
in php-mongo, i tried this:
$collection->find(array("between"=>array("user1", "user2", "user3")));
but it does not work.
What am i doing wrong ?
Wouldn't you want to do an In query here?
db.collection.find( { "between" : { $in : ["user1", "user2", "user3"] } } );
See In query here:
Mongo Advanced $in query
making your PHP query look like:
$collection->find(array("between"=>array("$in"=>array("user1", "user2", "user3"))));
//untested, should be something similar to this.
or if you're trying to find it exactly wouldn't you just be able to do:
$collection->find(array("between"=>array("user1,user2,user3")));
First of all when you are saving your data you have to use array not a string
{ "between" : [ "user1,user2,user3" ] }
this stores in "between" an array of one element "user1,user2,user3"
Basically when you do your query in shell everything is ok, because you are asking for a array with one element. But in php you are asking for an array of three elements.
So, when you save your data, most probably that is what you need :
{ "between" : [ "user1","user2","user3" ] }
and this will give you an array of three users.
Then read the documentation http://www.mongodb.org/display/DOCS/Advanced+Queries to and adjust your query depends on what you need: either the exact array or only some elements in the array
Have you tried:
$collection->find(array("between"=>"user1,user2,user3"));
or
$collection->find(array( "$elemMatch" => array( "between"=>"user1,user2,user3" ));
The $in operator is analogous to the SQL IN modifier, allowing you to specify an array of possible matches.
Consider the following example which uses the $or operator.
$collection->find([
'select' => ['$in' => ['option 1', 'option 2', 'option 3']]
]);
References
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.