Mongo DB: Change a field to array - php

Lets say we have a document like this
{
"_id" : "1234",
"Data" : {
"Name" : "Pythagoras",
"Like" : "Math"
}
And we changed over mind and want to push more things to Data->Like so it looks like;
{
"_id" : "1234",
"Data" : {
"Name" : "Pythagoras",
"Like" : ["Math", "Science"]
}
All the atomic operators like $push, $pushAll and $addToSet works just when Data->Like already is an array.
I´m using the php-driver. In this example there is no meaning to not set the Data->Like to an array at the beginning but it does not work like that in my code ;(
Hope you can help me and sorry for my bad English ;) Thanks!

You'll have to iterate over all your documents and change the value to an array. For example, you can do that with:
$m = new Mongo();
$c = $m->yourdbname->yourcollectionname;
foreach ( $c->find() as $r )
{
if ( !is_array( $r['Data']['Like'] ) )
{
$c->update( array( '_id' => $r['_id'] ), array( '$set' => array( 'data.like' => array( $r['data']['like'] ) ) ) );
}
}

Related

How to replace an element in an array

I have a COLLECTION collflokks in MongoDB, sample Document is :-
{
"_id" : "b_8AUL",
"f_name" : "Pizza. Hut",
"f_lat" : "22.7523513",
"f_lng" : "75.9225847",
"c_uid" : "33",
"f_type" : NumberLong(3),
"members" : [
"42",
"43"
]
}
Within the "members" array , I want to add Arrays like {id:42,name:Mark} , {id:43,name:Hughes}
Currently i'm adding just ids(eg.42,43). I'm only concerned about the new data as it will have new ids .Please suggest.
Earlier I was using this code to push into the members Array:
$flokkCollection = 'collFlokks';
$flokkCollection->update(
array("_id" => $f_handle),
array('$push' => array("members" => $u_id))
);
Well if what you are asking here is "replacing your existing data" then you need to "loop" the results from the collection and "replace" the array content that exists with your new format.
There are likely smarter ways to approach this, but you are not really giving us all the required information in your question, so I can only answer in the basic terms.
Presuming you have:
$required = array(
array(array("id" => "42"), array("name" => "Mark")),
array(array("id" => "43"), array("name" => "Hughes"))
);
As input, then you do something like this:
function myMapper($v) {
return $v["id"];
}
$mapped = array_map("myMapper",$required);
foreach( $mapped as $value) {
$filtered = array_values(
array_filter($required,function($k) {
return $k["id"] == $value;
})
)[0];
collection.update(array(
array("members" => $value),
array('$set' => array(
"members.$" => $filtered
))
));
}
Which should use the positional $ operator to find the matched "position" of the array element by the value used in the "query" portion of the update statement, then in the "update" portion of that statement $set that current array index to the new value at the "filtered" content index from the original input array.
Outside of PHP. We call these inner elements "objects" and not "arrays" which is a PHP notation trait. Key/value things are "objects" and "lists" are "arrays".

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

Find substring in MongoDB array from another array from PHP

I have a more complex document "schema" saved in Mongo but the part that I need to match looks like this
"tags" : [
{
"tag" : "accompong maroon festival",
"type" : "label"
},
{
"tag" : "jamaica",
"type" : "label"
},
{
"tag" : "maroon warrior",
"type" : "label"
},
{
"tag" : "maroons",
"type" : "label"
},
{
"tag" : "caribbean culture",
"type" : "label"
},
{
"tag" : "rum",
"type" : "label"
}
}
I am using PHP to query the Mongo database and I have to query each document against an array of possible words.
array(
'boxing',
'warrior'
)
I don't know how to write the code in order to try to match the array that I have with the dataset saved in Mongo.
For now I only try to see if the tag is within the array of words
$data = $this->event_model->find_by(
array
(
'tags.tag' => array
(
'$in' => $Words
),
'published' => 'y'
)
);
I've resolved this problem by first creating an array that uses MongoRegex to search through the tags and by adding this array to the $or procedure
$or_array = array();
foreach($Words as $w)
{
$or_array[] = array(
'tags.tag' => new MongoRegex('/.*'. $w .'.*/i')
);
}
$data = $this->event_model->find_by(
array
(
'$or' => $or_array,
'published' => 'y'
)
);

PHP - trying to make a JSON-like array and getting confused

I am using PHP and trying to create an array that looks something like this:
{
"aps" : {
"alert" : "Hey"
},
"custom_control" : {
"type" : "topic_comment",
"object":{
"topic_id":"123",
"topic_section":"test"
"plan_id":"456"
}
}
}
So far I have something like
$message = array('aps'=>array('alert'=>$some_variable));
but I am getting confused how I can put the values for "custom_control" into this array after that. Could anyone please advise how to do that from my existing php?
Thanks!
Is this what you mean?
<?php
$some_variable = "Hey";
$myArray = array(
"aps" => array(
"alert" => $some_variable
),
"custom_control" => array(
"type" => "topic_comment",
"object" => array(
"topic_id" => "123",
"topic_section" => "test",
"plan_id" => "456"
)
)
);
?>
Here is an easy way to discover what you need to do.
Create your JSON object.
Use it as input to the json_decode function.
Use the output of this as the input to var_export()
So supposing you assigned your JSON to $json_object, then use:
var_export(json_decode($json_object, true));
If you are more comfortable building the object in JSON you can use the JSON parser included in php. Also, JSON defines Javascript objects, not arrays (although you can define arrays in JSON with something like {myArray : [1,2,3]}
Try this if you want though:
http://php.net/manual/en/function.json-decode.php
If you've already created your initial message array (per your question), you would then do something like this.
$message["custom_control"] = array(
"type" => "topic_comment",
"object" => array(
"topic_id" => "123",
"topic_section" => "test",
"plan_id" => "456"
)
)
You can create whatever nodes you needs inside of $message this way.
What you are trying to create is not an array, but rather an object.
Try to not build it as an array but an object.
$obj = new stdClass();
$obj->aps = new stdClass();
$obj->aps->alert = 'Hey';
$obj->custom_control = new stdClass();
$obj->custom_control->type = 'topic_comment';
$obj->custom_control->object = new stdClass();
$obj->custom_control->object->topic_id = '123';
$obj->custom_control->object->topic_section = 'test';
$obj->custom_control->object->plan_id = '456';
$json = json_encode($obj);
$array = array();
$array['aps'] = "alert";
$array['custom_control'] = array();
$array['custom_control']['type'] = "topic_comment";
$array['custom_control']['object'] = array('topic_id' => '123',
'topic_section' => 'test',
'plan_id' => '456');
i think you need something like this:
$message =array( "aps" =>array("alert"=>"Hey"),
"custom_control" => array(
"type" => "topic_comment",
"object" => array(
"topic_id"=>"123",
"topic_section"=>"test",
"plan_id"=>"456"
)
)
);

Creat JSON object using php - nested queries

I want to create JSON object using tow query in PHP , Then retrieve this object using ajax . where the first one will return all users . the second nested query will return all tasks associated to particular user . The structure must be like this :
{
[
user1 : { "name" : "name1"
"task" : [ { "taskname":"taskname1.1" , "date":"1-1" } ,
{ "taskname":"taskname1.2" , "date":"1-1" }
}
} ,
user2: { "name" : "name2"
"task" : [ { "taskname":"taskname2.1" , "date":"2-2" } ,
{ "taskname":"taskname2.2" , "date":"2-2" }
]
}
...
]
}
my problem is :
when I try to parse each user's tasks , I found that :
each user's tasks are merged with the Previous user(s)' tasks .
So what is the best way to create JSON object with the same structure of mine using php ?
--- update ---
Thanks for everyone who answer me . But I need to know how to create this dynamically , I know how to do this in static and I use json_encode() correctly before , this is not my problem . I really appreciate your answers but this is not what I need and I think the problem is in my question .
$array=array(
'user1'=>array(
'tasks'=>array(
'task1'=>'whatever',
'task2'=>'whatever',
'task3'=>'whatever'
),
'date'=>'whatever'
),
'user2'=>array(
'tasks'=>array(
'task1'=>'whatever',
'task2'=>'whatever',
'task3'=>'whatever'
),
'date'=>'whatever'
),
'user3'=>array(
'tasks'=>array(
'task1'=>'whatever',
'task2'=>'whatever',
'task3'=>'whatever'
),
'date'=>'whatever'
)
);
Then use JSON encode to send the JSON string.
echo json_encode($array);
I agree with powerbuoy just create an array with key value pairs in php:
$obj = array(
"User 1" => array(
"name" => "name1",
"tasks" => array(
array("taskname" => "t1", "date" => "1-1"),
array("taskname" => "t2", "date" => "1-1")
)
),
"User 2" => array(...........)
then run json_encode($obj);
I think something like that should work for you

Categories