I'm having trouble assigning my own _id value when inserting a new document into my Mongo collection. Here's my PHP:
$user = array(
'_id'=> new MongoId("4f626fdf1771a8e71a000000"),
'name'=> 'John Smith'
)
try {
if($col->insert($user)){
echo 'INSERTED';
}
} catch(MongoCursorException $e) {
echo "ERROR: ".$e;
}
This does not display an error, but it also doesn't insert the item to the collection. However I can assign a string variable instead of the MongoId type to the _id field, and it inserts.
By default, MongoDB driver runs commands in so called 'unsafe mode', when it does fire-and-forget for requests and does not check for error. So, if there's a duplicate key error, you won't know.
Try running the insert in safe mode like this:
$col->insert($user, array("safe" => true));
Oh, and you most certainly can make your own ObjectIds (contrary to what other answers here say).
Safe has been deprecated from future usage. To ensure you are using the right command use the write concern 'w'.
$col->insert($user, array('w'=>true))
See here:
http://php.net/manual/en/mongocollection.insert.php
You cannot create MongoDB object IDs on your own. So, there are two ways to insert a document into a collection:
Let MongoDB create the ID (safe!)
Choose the ID on your own, it could be anything except an array and it needs to be unique.
Reference: Object IDs
I never used the combination of PHP and MongoDB but try to simple assign a string to the _id field.
Related
$connection->createCommand()->batchInsert('user', ['name', 'age'], [
[$names, $ages],
])->execute();
I know that i can do a batch insert using the code above in Yii 2. But how can i prevent duplicate entry using batchInsert? For example, if I have a duplicate name, i dont want to insert it in the db
Two possible options:
1) Use unique constraint for name column in your database table.
That way you just try to execute query and catch exception:
try {
// Your query goes here
} catch (\yii\db\Exception) {
// Handle error
}
\yii\db\Exception is more common database operations related exception, you can use more specific \yii\db\IntegrityException.
2) Exclude duplicates from array in PHP before feeding data and executing query. Depending on how array is constructed you can do it:
during building this array in foreach for example by checking if item with same name already exists in formed array, if yes - append element to it, otherwise - skip.
or afterwards using for example array_filter function.
I recommend first approach, because even you decide to handle duplicates in PHP, according data structure and additional protection in database won't be superfluos.
I have an external database that I am trying to access from within a Drupal page, I have successfully queried the database and output data to the page using fetchAssoc(), however this only returns the first row in the database. I would like to return all rows into an array for processing, so I'm attempting to use fetchAllAssoc(), this however results in an exception. The database has the following SQL fields:
id, model, manufacturer, url, date_modified
My test code is as follows:
<?php
db_set_active('product_db');
$query = db_select('product', 'p')->fields('p');
$sqlresults = $query->execute()->fetchAllAssoc('id');
foreach($sqlresults as $sqlresult)
{
printf($sqlresult);
}
db_set_active();
?>
I'm thinking that it is the key field 'id' that I am specifying with fetchAllAssoc() that is the problem, as fetchAssoc() prints values correctly. All documentation I have found seems to say that you pass a database field as the key but I have also passed a numeric value with no success.
Many thanks in advance for any advice, I'm sure I'm just missing something stupid.
I think it should work in this way, but within the foreach you want to print the $sqlresult variable as a string, but it is an object (it causes the error).
printf function needs a string as the first parameter, see:
http://php.net/manual/en/function.printf.php
Use for instance var_dump instead:
var_dump($sqlresult);
I have a strange situation.
Suppose I have a very simple function in php (I used Yii but the problem is general) which is called inside a transaction statement:
public function checkAndInsert($someKey)
{
$data = MyModel::model()->find(array('someKey'=>$someKey)); // search a record in the DB.If it does not exist, insert
if ( $data == null)
{
$data->someCol = 'newOne';
$data->save();
}
else
{
$data->someCol = 'test';
$data->save();
}
}
...
// $db is the instance variable used for operation on the DB
$db->transaction();
$this->checkAdnInsert();
$db->commit();
That said, if I run the script containing this function by staring many processes, I will have duplicate values in the DB. For example, if I have $someKey='pippo', and I run the script by starting 2 processes, I will have two (or more) records with column "someCol" = "newOne". This happens randomly, not always.
Is the code wrong? Should I put some constraint in DB in form of KEYs?
I also read this post about adding UNIQUE indexes to TokuDB which says that UNIQUE KEY "kills" write performance...
The approach you have is wrong. It's wrong because you delegate the authority for integrity/uniqueness check to PHP, but it's the database that's responsible for that.
In other words, you don't have to check whether something exists and then insert. That's bad because there's always some slight ping involved between PHP and MySQL and as you already saw - you can get false results for your checks.
If you need unique values for certain column or combination of columns, you add a UNIQUE constraint. After that you simply insert. If the record exists, insert fails and you can deal with it via Exception. Not only is it faster, it's also easier for you because your code can become a one-liner which is much easier to maintain or understand.
I am currently learning MongoDB. I have seen tutorials for querying a field in a collection. I would like to know how to query in PHP using the MongoId Object _id value. The closest answer to my question is at Perl Mongo find object Id .
Also, is there a way that when a new record is created, the Object _id value can be recorded in another field of that record?
Thanks.
Update:
In addition to the answer I chose below, a coworker found this as well:
mongodb php findone() by ID
This should help, from the mongodb web site (http://blog.mongodb.org/post/26903435041/mongodb-for-the-php-mind-part-2):
// This is only a string, this is NOT a MongoId
$mongoid = '4cb4ab6d7addf98506010000';
// You will not find anything by searching by string alone
$nothing = $collection->find(array('_id' => $mongoid));
echo $nothing->count(); // This should echo 0
// THIS is how you find something by MongoId
$realmongoid = new MongoId($mongoid);
// Pass the actual instance of the MongoId object to the query
$something = $collection->find(array('_id' => $realmongoid));
echo $something->count(); // This should echo 1
Regarding part of your question, I'm not aware of any automated way to store the objectid in another field but I'm also not aware of why you would want to do that - you already have it stored in _id, why would you want it in another field?
Creating a document:
$db->collection->insert($content);
// $newDocID = ???
I'm trying to get the new document's id. How? Thanks.
According to the docs the array you pass to insert will be amended with an _id field:
$db->collection->insert($content);
$newDocID = $content['_id'];
You can also get _id before insert. Just add _id field to document with new MongoId ie.
$content['_id'] = new MongoId();
$db->collection->insert($content);
Also there are nice benefits of this:
You don't need fsync flag like posted in comment by ZagNut in
previous answer. So you don't need to wait for reply from DB.
You don't need to actually insert anything to DB to get id. So you can
prepare some related objects and then insert or not insert them -
somewhat like transactions which mongo does not support (yet?).
You actually can generate id in your application, not in db, So you can
do whatever you want before or after insert.
This works for me:
$insertResult = $collection->insertOne($object);
$id = $insertResult->getInsertedId();
$newDocument = $db->collection->findAndModify ( $row, $row, null, array('new'=>true,'upsert' => true));
$strId = $newDocument['_id']->{'$id'};
http://php.net/manual/en/mongocollection.findandmodify.php