Update MongoDB sub document element based on the Condition using PHP - php

Here is my JSON Array
{
"_id" : ObjectId("563b57c84abf457b395076f0"),
"project_id" : "563b57c84abf45ce1f5076f1",
"project_task" : [
{
"switch" : "Ball",
"deviceId" : "dasdqwdf124",
"slot" : "2344",
"MigrationStartDate" : "",
"MigrationEndDate" : "",
"MigrationStatus" : "",
"task_id" :12
}
]
}
In this array project_id and task_id (Sub Document element) values are unique.
So in this case i need update my sub document element one at a time When project_id and task_id are equals to given values.
So far i used update function with and condition and findAndModify() function but never worked for me.
Here is my Query using findAndModify()
findAndModify(array('project_id' => "$projectId", 'project_task' => array('task_id' => "$taskId")), array('$set' => array("$column" => "$value")))
Please help me out

Related

Convert PHP mongodb findOne result to old associative array?

I'm having issues with the new mongodb driver for php.
While iterator_to_array works ok for ->find, if I only return one document it has MongoDB\Model\BSONDocument format.
$result = $db->clients->findOne(array('_id' => $id));
$result = (array) $result;
In Mongo the document looks something like:
{
"_id" : ObjectId("3894713i4b13iu412"),
"active" : true,
"logo" : "this is logo",
"settings" : {
"email" : "days",
"testMode" : false
},
"stats" : {
"f" : {
"all" : [
{
"count" : NumberLong(15846),
"sum" : NumberLong(149479)
},
{
"count" : NumberLong(15846),
"sum" : NumberLong(148891)
},
{
"count" : NumberLong(15846),
"sum" : {
"1" : NumberLong(15522),
"2" : NumberLong(324)
}
}
]
},
"l" : {
"order" : ISODate("2016-12-05T09:10:53.855+0000"),
"feedback" : ISODate("2016-12-05T08:34:48.403+0000")
}
},
"title" : "hhh.ro",
"url" : "sdfasdf"
}
This will only turn first level elements into an array, but nested document elements still remain MongoDB\Model\BSONDocument;
iterator_to_array doesn't work because this is not something iterable.
How do I convert entire document to an associative array like the old mongo driver or a stdClass?
you can set how the data is returned globally in database->setCollection options, Set typeMap to array
'typeMap' =>[
'document' => 'array',
'root' => 'array'
]
Link to Doc
I couldn't find the setCollection suggested by #Delcon in PHP MongoDB library so I used the below method.
typeMap option can also be set in the options array inside findOne.
$someCollection->findOne(
[],
['typeMap' => ['root' => 'array', 'document' => 'array', 'array' => 'array']]
);
Link to Doc
edit:
You could also pass the options array to the connector to set it globally as described by this Stackoverflow post.
$options = ["typeMap" => ['root' => 'array', 'document' => 'array']];
$conn = new MongoDB\Client("mongodb://localhost:27017", [], $options);

Position operator '$' is not working in Mongo PHP 5.5

Here I need to insert another array data where there is already an existing record in MongoDB.
Example:
Already existing record in db:
{
"_id" : 1,
"name" : "main",
"sample_details" : [
{
"detail_no" : 1,
"email" : "test#gmail.com",
"name" : "test",
},
{
"detail_no" : 2,
"email" : "test12#gmail.com",
"name" : "test12",
}
],
}
Suppose I need to insert one more array data in "sample_details". Here is my code, but the position operator "$" is not supporting. May I know the exact solution for my query:
Code:
$array = array(
'sample_details.$.detail_no' => 3,
'sample_details.$.email' => "test123#gmail.com",
'sample_details.$.name' => "test123",
);
$this->mongo_db->update(table_name,array('_id'=>1),array('$set'=>$array),array('multiple'=>true));
To insert data into array you want to use operators like $push, $pushAll or $addToSet.
You can't use positional operator because citing its documentation:
the array field must appear as part of the query document.
Also it only makes sense when you're updating an array's element and you don't know its index, not inserting new things.

MongoDb Update only one value from array

I have a collection in mongodb which looks like this.
"_id" : ObjectId("554c5397ccfff21e103c9869"),
"name" : "test",
"color" : [
"552ced22ccfff2d8183c986a_Jellow",
"551fdd24ccfff2362e3c9869_test"
],
"updated_at" : ISODate("2015-05-08T06:11:35.303Z"),
"created_at" : ISODate("2015-05-08T06:11:35.303Z")
I want to update only one value in the array color But when i try to update the array it removes all the values from the color array and replaces it by the new value.
Here is the code. (I AM USING JESSENGER MONGODB PACKAGE FOR LARAVEL)
$query->where($field,'regexp','/^('.$id.')_.*/')->update([$field=>$id.'_'.$name]);
How should i do it.??
What you wanna do is, either change your schema as {key: value} pair and then follow this tutorial, that will help you to sort out your problem. OR you can get all the values from color array and replace with new value and then update your document (I would not go for it coz it is a dirty approach!).
EDIT
Hey Bud! I founded this, on jenssenger docs:
Push
Add an items to an array.
DB::collection('users')->where('name', 'John')->push('items', 'boots');
DB::collection('users')->where('name', 'John')->push('messages', array('from' => 'Jane Doe', 'message' => 'Hi John'));
If you don't want duplicate items, set the third parameter to true:
DB::collection('users')->where('name', 'John')->push('items', 'boots', true);
Pull
Remove an item from an array.
DB::collection('users')->where('name', 'John')->pull('items', 'boots');
DB::collection('users')->where('name', 'John')->pull('messages', array('from' => 'Jane Doe', 'message' => 'Hi John'));
You need to use the $set operator. Not sure how it's done in Jessenger Mongodb, but it might be something like:
$query->where($field,'regexp','/^('.$id.')_.*/')
->update(['$set' => [ $field=>$id.'_'.$name]]);
Why don't change your data like this:
"_id" : ObjectId("554c5397ccfff21e103c9869"),
"name" : "test",
"color" : [
{ "id":"552ced22ccfff2d8183c986a", "name":"Jellow"},
{ "id":"551fdd24ccfff2362e3c9869", "name":"test"}
],
"updated_at" : ISODate("2015-05-08T06:11:35.303Z"),
"created_at" : ISODate("2015-05-08T06:11:35.303Z")
then you can update element by id.

PHP/MongoDB $set use for update an array in a collection

I am trying to update() a specific single array in a collection, but while it works fine with $push parameter on a single, specific array, it does not work with a $set parameter.
I don't quite understand logic behind that, because when I use such an example of $pushing the element:
$post_comment = array('$push' =>
array("comments" => array(
"_id" => new MongoId(),
"comment" => htmlspecialchars($_POST['comment']),
"author" => $user->username,
"date" => new MongoDate()
)
)
);
$entries->update(array(
"_id" => $_GET["id"]), $post_comment);
It gives me an array in a MongoDB database which looks more or less like this (with four items pushed in, respectively) :
{
"_id" : "css-clearfix-explained",
"comments" : [
{
"_id" : ObjectId("540cc940af105b19133c9869"),
"comment" : "aaa",
"author" : "maciejsitko",
"date" : ISODate("2014-09-07T21:08:16.215Z")
},
{
"_id" : ObjectId("540cc943af105b19133c986a"),
"comment" : "bbb",
"author" : "maciejsitko",
"date" : ISODate("2014-09-07T21:08:19.542Z")
},
{
"_id" : ObjectId("540cc946af105b19133c986b"),
"comment" : "ccc",
"author" : "maciejsitko",
"date" : ISODate("2014-09-07T21:08:22.968Z")
}
]
}
Which is basically what I want to have, and logically, works fine according to the documentation. But when I try the same with $set as for to edit an individual comment, in the similar fashion as shown:
$edit_comment = array('$set' =>
array("comments" => array(
"_id" => new MongoId($_POST['cmt-id']),
"comment" => htmlspecialchars($_POST['edit-comment']),
"author" => $user->username,
"date" => new MongoDate()
)
)
);
$entries->update(array(
"_id" => $_GET["id"]), $edit_comment);
It outputs four different arrays in place of the previous arrays, to illustrate that, i'll show what happened when I updated first comment "aaa" to "ddd" :
{
"_id" : "css-clearfix-explained",
"comments" : {
"_id" : ObjectId("540cc940af105b19133c9869"),
"comment" : "ddd\r\n ",
"author" : "maciejsitko",
"date" : ISODate("2014-09-07T21:12:10.833Z")
}
}
All the four array elements were pretty much erased and in their place appeared four fields as four independent array elements.
How come? Shouldn't it just work just fine like the example with $push above?
You didn't specify an index within comments. Therefore, $set replaced the array comments with the associated array supplied.
If you want to update a comment, then change your query in the first argument to match a comment by a unique field. Ex, date. In the second argument use a positional $ operator.
Example:
$edit_comment = array('$set' =>
array("comments.$" => array(
"_id" => new MongoId($_POST['cmt-id']),
"comment" => htmlspecialchars($_POST['edit-comment']),
"author" => $user->username,
"date" => new MongoDate()
)
)
);
// this assumes the post date is unique. On second though use something else.
$query = array( "_id" => $_GET["id"], "comments.date" => $_POST['post-date'])
$entries->update( $query, $edit_comment);
Check this out for more info and better explanation:
MongoDB - $set to update or push Array element

Mongodb + PHP => Find query operator in multidimensional array

I need to find in array saved in a document of Mongodb.
Here is the document :
{
"hashtag" : "World",
"topimages" : [
{
"cluster" : "france",
"id_tw" : "477170636327227393"
},
{
"cluster" : "france",
"id_tw" : "477170636327227396"
}
]
}
And I want to search if a document named "World" by key "hashtag", have already a tweet saved in the array "topimages" with an id "id_tw" of value : "477170636327227393"
What I'm trying to do is :
$query = array('hashtag' => "World", array('topsimages.$.id_tw' => "477170636327227393"));
$xpmm->find($query);
I need to search if a document called "World" has already a tweet saved in the array "topimages" by his key "id_tw".
Thanks a lot.
#
Solution :
$query = array('hashtag' => "france", 'topimages.id_tw' => "477170282852286464");
That's ok using :
$query = array('hashtag' => "france", 'topimages.id_tw' => "477170282852286464");
topimages.x would only work if it was a subdocument, not an array. You want $elemMatch (Mongo DB Documentation)
$query = array('hashtag' => "World", 'topsimages' => array("$elemMatch" => array("id_tw" => "477170636327227393")));

Categories