Mongo DB, PHP add or update a field in a document - php

I have the following document:
{
"_id": ObjectId("5241f1d79b7e7aed05000000"),
"description": {
"nl": "Hallo",
"en": "Hello"
},
"name": "Marc"
}
Now I need to update to update one existing field or add new field to the description. In php I use the update function for Mongo and the following code:
$new_data = array(
'$set' => array(
"description" => array(
"de" => "hallo"
)
)
);
What it does it removes all other fields and just insert the "de" field. I tried replacing $set with $push (which I thought was made for this) but no result also $setOnInsert does not do anything.
How can I solve this problem so that I can either add a new field (if it does not exist) or update if it exist.
Thanks

Just make your update like
{$set: {"description.de": "hello"}}
I guess in your code it would be:
$new_data = array(
'$set' => array(
"description.de" => "hallo"
)
);

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

How to update inner array in MongoDb document

I'm trying to add php array to MongoDB document
{
"_id" : ObjectId("51b043e1d07a4e9e06000004"),
"comments" : {
"count" : 0,
"array" : []
}
}
array:
$array = array(
"user_id" => $comment["user_id"],
"text" => $comment["text"]
);
Using this:
$this->database->Collection->update(array("_id" => new MongoId($comment["object_id"])), array('$push' => $array);
However, it doesn't seem to work and I can't find why. I don't know MongoDb well yet... Thanks
The value of the $push needs to be another PHP array with a key that names the array field to update and a value that's the element to add. So in this case it would be:
$this->database->Collection->update(
array("_id" => new MongoId($comment["object_id"])),
array('$push' => array("comments.array" => $array)));

MongoDB PHP accent problems

Assume that I have inserted the following document with PHP (Note the "ó".)
$dbs->insert(array('name' => 'televisión'));
In mongodb database server is saved as follows
{ "name" : "televisi��n" }
If I invoke the findOne method as follow, (NOTE THE ó)
$doc = $dbs->findOne(array('name' => "televisión"));
It return me the correct value
[name] => televisión
Everything fine until here.
So, imagine that from php I need to determine that the document televisión is into mongodb database, but I get the value from an URL without the accent "ó", i.e. television, so.
$doc = $dbs->findOne(array('name' => "television"));
findOne method is returning null, so don't match the document.
Is there any way for this not return null value and can find the document regardless of the accent?
Thanks in advance!
In mongodb database server is saved as follows
{ "name" : "televisi��n" }
That's probably because your shell doesn't show UTF-8 properly.
As for:
Is there any way for this not return null value and can find the document regardless of the accent?
You can do that with the new text search functionality:
<?php
$m = new MongoClient;
$d = $m->test;
$c = $d->so;
// Just dropping here to create a controlled output - no need to do this yourself.
$c->drop();
$c->ensureIndex(
array( 'name' => 'text' ),
array( 'default_language' => 'spanish' )
);
$c->insert( array('name' => 'televisión' ) );
$res = $d->command( array( 'text' => 'so', 'search' => 'television' ) );
var_dump( $res['results'] );
?>
Which outputs:
array(1) {
[0] =>
array(2) {
'score' =>
double(1)
'obj' =>
array(2) {
'_id' =>
class MongoId#6 (1) {
...
}
'name' =>
string(11) "televisión"
}
}
}
For text search to work, you need MongoDB 2.4.x, and you need to specifically enable it with the --setParameter textSearchEnabled=true flag to mongod or add to your code:
$d->command( array( 'setParameter' => 1, 'textSearchEnabled' => true ) );

update an embedded document in mongodb using php

I am making a blogging site so I am using MongoDB as my DB. In my collection "articles", I have 1 embedded doc named posts and I want to insert 1 more embedded doc. comments into it.
DB:
{
"_id": ObjectId("4f41a5c7c32810e404000000"),
"username":"abc",
"posts": [
{
"_id": 1,
"content": "dskcnkdcnksldcnskcd",
"title" : "test1"
},
{"_id": 2,
"content": "dskcsdsl;d,cl;sdcl;sdmcnkdcnksldcnskcd",
"title" : "test2"
},
]
}
I want to insert comments into posts.
{
"_id": ObjectId("4f41a5c7c32810e404000000"),
"username":"abc",
"posts": [
{
"_id": 1,
"content": "dskcnkdcnksldcnskcd",
"title" : "test1",
"comments":[
{
"content": "usdhcjsdcjskd",
"by" : "abc"
}
]
},
{"_id": 2,
"content": "dskcsdsl;d,cl;sdcl;sdmcnkdcnksldcnskcd",
"title" : "test2"
}
]
}
Comments is actually an embedded document of posts in your document as such you need to change your query a little to:
$collection->update(array('_id' => new MongoId($bid),'posts.id'=> $pid),array('$push' => array('posts.$.comments' => $comment)));
Try that.
Notice how I have used the positional operator? You can read more about it here: http://www.mongodb.org/display/DOCS/Updating/#Updating-The%24positionaloperator
the thing you need to be careful is your structure for first insert. For example you have some user with some lists and you want to let him to have up to 5 lists. This is how you can do it with PHP:
You need to install your mongodb extension if you do not have it in your PHP environment on your localhost server
You need to install mongodb and run it.
After all that is done you can easily do it like this:
$m = new Mongo("mongodb://localhost");
$db = $m->statistic->list;
// statistic is my database and list are collection.
$list =
array(
'_id' => 18,
'lists' =>
array(
array(
'name' => 'Magento and PHP developer',
'recipients' =>
array(
'name' => 'Kristijan Glibo',
'email' => 'glibo.kristijan#gmail.com'
),
'count' => 12345),
));
You can see here that I use some (int)18 for my _id. If you do not specify it, Mongo will generate it. I use it like this just for testing purposes. Notice here that lists are array and every list inside it are array too with their own data! My list Magento and PHP developer have data about recipients and count. Recipients also have some unique data.
Lets make first insert into our Mongodb:
$document = $db->insert($list);
If we now dump collection to check out what we saved inside of it we will get this:
NOTE: To get your collection and everything inside it you can use this code:
$documents = $db->find();
echo '<pre>';
foreach ($documents as $doc) {
var_dump($doc);
}die();
********************this is dumped data*******************
["_id"]=>
int(18)
["lists"]=>
array(3) {
[0]=>
array(3) {
["name"]=>
string(10) "Magento and PHP developer"
["recipients"]=>
array(2) {
["name"]=>
string(4) "Kristijan Glibo"
["email"]=>
string(25) "glibo.kristijan#gmail.com"
}
["count"]=>
int(12345)
}
Lets now update our user and add him more lists:
$updatelist = array('name' => 'updatelist', 'recipients' => array(),'count'=>2876);
$documentupdate = $db->
update(
array('_id'=>18),
array('$addToSet' => array('lists'=> $updatelist)));
You are telling him which object to update by selectin _id => 18 and how to update. I test this and it will add new list if that list do not exist. If exist it will skip it.
Hope this helps!

Categories