Using $all to match values inside an array inside of another array - php

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"]});

Related

php json_decode not returning any results

i am trying to figure out why i am not returning any data when i use json_decode. i'm trying to get values that are in a valid json file (yes, i tested it). when i try and use:
foreach($json['designs']['filters'] as $filters) {
echo $filters['filterTypeName'];
}
i am returning the values ... that's great, but i am trying to get down to the next level of the json file to pull just the values for each array under "values". here is the json file results from file_get_contents('url'):
{"designs": {
"filters" :
[
{
"filterTypeName":"Year",
"filterProperty":"year",
"values":
[
{
"name":"2018",
"value":"2018",
"sortvalue":"1"
},
{
"name":"2017",
"value":"2017",
"sortvalue":"2"
}, (etc.)
]
},
{
"filterTypeName":"Division",
"filterProperty":"division",
"values":
[
{
"name":"Resort-Apparel",
"value":"Resort-Apparel",
"sortvalue":"1"
},
{
"name":"College-Apparel",
"value":"College-Apparel",
"sortvalue":"2"
}, (etc.)
]
}, (etc.)
essentially, i have a select options on my form that checking against the values listed above to return designs that match the criteria.
how do i specifically search for all of the years in one select group, then all of the divisions in another select group and so-on?
thanks for any and all of your help!!
Try using $json->designs-> filters for accessing filters instead of $json['designs']['filters']
As the others have said, json_decode returns an object unless true is specified as the second parameters, so your options are either:
Use $json->designs->filters
or use json_decode($json, true)
i used foreach($json['designs']['filters'][0]['values'] as $name) i forgot to specify the number of the array i was trying to access.

\MongoDB\BSON\Regex in aggregation pipeline - Convert regex from Python to PHP

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.

Remove item from array in a mongodb document using Doctrine ODM

I have a mongoDB document comprising the following structure:
{
"_id" : ObjectId("537b9731fa4634134c8b45aa"),
"kpis" : [
{
"id" : 4,
"value" : 3.78,
"entered" : Timestamp(1401377656, 9)
}
]
}
I want to remove ALL kpi documents where the id is x. This is quite simple to do on the database directly using the pull command:
db.lead.update({}, {$pull:{"kpis":{id:5}}}, {multi:true});
However my (several) attempts to match this syntax using the doctrine ODM have failed:
$qb->update()
->field('kpis')
->pull($qb->expr()->field('kpis.id')->equals($kpi->getId()))
->multiple(true)
->getQuery()
->execute();
// I've also tried..
$qb->update()
->field('kpis')
->pull($qb->expr()->field('kpis')->elemMatch(
$qb->expr()->field('kpis.id')->equals($kpi->getId())
))
->multiple(true)
->getQuery()
->execute();
Nothing is removed. Am I using the query builder correctly?
I believe you want to do the following:
$qb->update()
->field('kpis')->pull(array('id' => $kpi->getId()))
->multiple(true)
->getQuery()
->execute();
You can use the Query::debug() method to dump the actual query generated by this. You should expect the following in the dumped newObj field:
{ "$pull": { "kpis": { "id": <number> }}}
To explain why your previous examples didn't work:
->field('kpis')
->pull($qb->expr()->field('kpis.id')->equals($kpi->getId()))
Here, you're creating the following query:
{ "$pull": { "kpis": { "kpis.id": <number> }}}
This would only match:
If each embedded object in the top-level kpis array had an embedded kpis object within it, which in turn had an id field that matched the number.
If the embedded objects in the top-level kpis array had their own kpis arrays consisting of embedded objects with an id field that matched. This would be MongoDB's array element matching coming into play.
In your second example, you have:
->field('kpis')
->pull($qb->expr()->field('kpis')->elemMatch(
$qb->expr()->field('kpis.id')->equals($kpi->getId())
))
This would generate the following query:
{ "$pull": { "kpis": { "$elemMatch": { "kpis.id": <number> }}}}
I've never seen such syntax before, but I think the $elemMatch is superflous, since $pull already takes criteria to match an array element as its argument. $elemMatch is useful in a query when you're directly matching on an array field and don't mean to do a full equality match against the array elements (i.e. you want to provide criteria instead of an exact match).

Update a couple of values in nested array MongoDB

I would like to update a couple of elements in they match given values:
Example : I have a collection with this structure:
{
"_id" : ObjectId("52936a0270c68c04063f0300"),
"channel" : "1",
"content" : "145548",
"keywordsValues" : [
[ObjectId("52816d3370c68c2c1c4b0500"), ObjectId("52816d3370c68c2c1c9f0500")],
[ObjectId("52816d3370c68c2c1c510500"), ObjectId("52816d3370c68c2c1c890500")],
[ObjectId("52816d3370c68c2c1c550500"), ObjectId("52816d3370c68c2c1c850500")],
[ObjectId("52816d3370c68c2c1c6b0500"), ObjectId("52816d3370c68c2c1c990500")]
]
}
And I need to update "keywordsValues" field (just one of the couple in the array [])
Something for example update the 2nd element in keywordsValues:
If we found [firstId,secondId] in keywordsValues field then update the second secondId
$database->Measurements->update(
array('keywordsValues'=>
array(new MongoId(52816d3370c68c2c1c4b0500),new MongoId(52816d3370c68c2c1c9f0500)',$atomic'=>'true')),
array('$set'=>array('keywordsValue.$'=>new MongoId($idNewValue))));
But this doesn't work...
try
array('$set'=>array('keywordsValue'=>new MongoId($idNewValue))));
instead of
array('$set'=>array('keywordsValue.$'=>new MongoId($idNewValue))));
i hope it help to you!

Query mongodb with php-mongo

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

Categories