I’m using graphaware/neo4j-php-client 4.5.1 with Neo4j 3.0.4 on PHP 5.6.24.
I don’t understand how to find out whether a transaction has failed.
For example, I try to delete a node that still has relationships. If I run the DELETE in this simple query:
$client->run
(
'MATCH (node { name: {name} }) DELETE node',
[ 'name' => 'Fred' ]
);
… I get this exception, which is the behaviour I expected:
[GraphAware\Neo4j\Client\Exception\Neo4jException]
org.neo4j.kernel.api.exceptions.ConstraintViolationTransactionFailureException:
Cannot delete node<31>, because it still has relationships.
To delete this node, you must first delete its relationships.
But when I wrap that same query inside a transaction:
$transaction = $client->transaction();
$transaction->push
(
'MATCH (node { name: {name} }) DELETE node',
[ 'name' => 'Fred' ]
);
$results = $transaction->commit();
foreach ($results as $result)
{
$summary = $result->summarize();
$stats = $summary->updateStatistics();
printf("Nodes deleted: %d\n", $stats->nodesDeleted());
}
printf("Transaction status: %s\n", $transaction->status());
… Neo4j doesn’t delete the node, but I see this (suggesting success) instead of an exception:
Nodes deleted: 1
Transaction status: COMMITED
Am I missing anything, or is this a bug? Thanks in advance!
Thanks,
This is actually a bug and I fixed it in https://github.com/graphaware/neo4j-php-client/commit/af8f01475a3cf63549498449574eb9c4bb8e7254
The 4.5.3 version including this fix should be available on packagist in a couple of minutes.
Please test and report back.
Related
I am using jenssegers package in Laravel 5 for mongodb.
I am inserting multiple data in below described way and data is inserted successfully in mongodb but then it through error before the script completes.
$AllTrans=array();
$AllTrans[]=array("InvoiceID"=>1,"Amount"=>50);
$AllTrans[]=array("InvoiceID"=>2,"Amount"=>150);
$mongo_connnection->collection('invoices')->insert($AllTrans);
Here is the error:
MongoException in Collection.php line 42:
No write ops were included in the batch
But i can not figure out problem, I have tried passing option like array('multi' => true) with insert query but it was not working.
It will work great with bulk addition, this way, you just need to create on array and pass it to it.
$temp = [
[
'item'=> "envelopes"
],
[
'item'=> "envelopesas"
],
[
'item'=> "lala"
]
];
$userData = DB::table('log')->raw( function ( $collection ) use ($temp) {
return $collection->insertMany($temp);
});
I'm trying to test an artisan command that is designed to do some database maintenance.
In particular, it searches for records that don't have a column filled, and fill it.
This is a simplified version of the fire() method of the command:
public function fire()
{
$items = Item::all();
$total = $items->count();
$updated = 0;
foreach ($items as $item) {
if ($item->myColumn != 'x') {
$item->myColumn = 'x';
$item->save();
$updated++;
}
}
$this->info("total: $total updated: $updated");
}
My (acceptance) test is very simple and does the following:
insert a record in the db
call the artisan command
check that the inserted record has been updated
This is the code:
public function doTheTest(AcceptanceTester $I)
{
$I->wantTo('setup the myColumn when it is not set');
$id = $I->haveRecord('items', [
'myColumn' => '',
]);
$I->runShellCommand('php artisan items:updater');
$I->seeRecord('items', [
'id' => $id,
'myColumn' => 'x',
]);
}
However the test fails, and I get the following message:
Couldn't see record "items",{"id":101,"myColumn":"x"}:
Couldn't find items with {"id":101,"code":"x"}
As you can see, the id of the new record is 101, because there are already 100 items in the db dump, but what it is strange is that the $this->info() in the command prints
total: 100 updated: 100
as if the database used inside the test and the one used inside artisan are different.
Moreover, if at the end of the test I try to grab the added record, and print it, as shown in the following snippet
public function doTheTest(AcceptanceTester $I)
{
/* ... */
$item = $I->grabRecord('items', [
'id' => $id,
]);
\Codeception\Util\Debug::debug($item);
}
and run the codecept run acceptance --debug command, I get the added record
stdClass Object
(
[id] => 101
[myColumn] =>
)
I'm very confused, because the there is a single database, but I'm surely misunderstanding something important here.
Could anyone give me a help?
Thank you very much,
The issue is that every query using Laravel4 module is run in a transaction that, by default, will be rolled back at the end. If you take a look at the Config section of Laravel4 documentation it states
cleanup: boolean, default true - all db queries will be run in transaction, which will be rolled back at the end of test.
You can check this if you restart the MySQL server (in which case, when you run the tests again you'll still see the id 101), or take a look at MySQL logs that will have an entry like the following for each test:
150417 23:24:24 2 Connect root#localhost on laravel-test
2 Prepare set names 'utf8' collate 'utf8_unicode_ci'
2 Execute set names 'utf8' collate 'utf8_unicode_ci'
2 Close stmt
2 Query START TRANSACTION
2 Prepare insert into items (myColumn) values (?)
2 Execute insert into items (myColumn) values ('')
2 Close stmt
2 Query ROLLBACK
2 Quit
To fix this, you need to configure the option cleanup of Laravel4 module in your codeception.yml file, like this:
modules:
config:
Laravel4:
cleanup: false
I am new to MongoDB and trying to perform my first updates.
I have my users collection that is populated by an insert statement. Now, I want to add or insert the field authCode with some data into a specific user.
My problem is that when I perform the following function the whole user data becomes replaced by the information in that update statement. My understanding is that by using upsert I would insert or update a users collection. given that the user already exist I expect just the authCode field to be created or updated.
Could anyone point out what am i doing wrong?
public function addAuthCode( array $userId, $code ) {
$user = $this->db()->user;
$user->update(
$userId,
array( 'authCode' => $code ),
array( 'upsert' => true, 'safe' => true )
);
}
You'll want to take a look at the MongoDB documentation for updates found here: http://docs.mongodb.org/manual/reference/method/db.collection.update/#db.collection.update
Specifically:
Add New Fields
db.bios.update(
{ _id: 3 },
{ $set: {
mbranch: "Navy",
"name.aka": "Amazing Grace"
}
}
)
Notice that in order to add a field, you need to use the $set operator
Chris#MongoLab
I have lots of records in a collection. They are indexed with a binary uuid :
db.users.find().limit(1);
[{ "_id": ..., "guid": BinData(2,"EAAAANR56IodpE3xhYLtfugc7SY="), otherdata }]
If I query from the CLI, I can retrieve the records:
db.users.find({ "guid": BinData(2,"EAAAANR56IodpE3xhYLtfugc7SY=") });
[{ "_id": ..., "guid": BinData(2,"EAAAANR56IodpE3xhYLtfugc7SY="), otherdata }]
If I want to do the same thing from PHP, the query returns nothing:
$client->db->setProfilingLevel(2);
$res = $client->db->users->find(array('guid' => new MongoBinData($bin_data, 2)));
$res->next(); // perform the query
echo $res->count(); // display 0
Of course I have tested the $bin_data variable hold the right value.
If I look at mongo's logs,
Thu Jan 10 18:05:06 [conn1] query db.users query: { guid: BinData } ntoreturn:0 ntoskip:0 nscanned:0 keyUpdates:0 locks(micros) r:14807 nreturned:0 reslen:20 14ms
the scanned value is 0 ! This means it does not even scan the collection for results ?
Any clue ?
Edit I have set the profiling level to 2, it does change anything. I can see authentication in the logs but still no query.
Edit2 Added log line.
I must admit I am confused myself. I ran:
$mongo = new Mongo();
$db = $mongo->mydb;
$col = $db->gjgjgj->insert(
array( "guid" => new MongoBinData("EAAAANR56IodpE3xhYLtfugc7SY=", 2) )
);
var_dump($col);
$cur = $db->gjgjgj->find(
array( "guid" => new MongoBinData("EAAAANR56IodpE3xhYLtfugc7SY=", 2) )
);
var_dump(iterator_to_array($cur));
And my output was:
boolean true
array
'50ef0bc96803fa0b04000000' =>
array
'_id' =>
object(MongoId)[7]
public '$id' => string '50ef0bc96803fa0b04000000' (length=24)
'guid' =>
object(MongoBinData)[9]
public 'bin' => string 'EAAAANR56IodpE3xhYLtfugc7SY=' (length=28)
public 'type' => int 2
Can you tell us what PHP driver version this is?
Can you also post your entire script that can reproduce this?
Edit
Of course running count() after running a next() on the cursor works for me too.
Mongo doesn't log all queries by default. Only slow queries (usually taking more than 100 milliseconds) are logged. Also check out docs on profiling.
You can use mongoDB profiling from php to see what is happining there
http://php.net/manual/en/mongodb.setprofilinglevel.php
$this->command(array('profile' => 2))
What I want:
fetch some documents
for every document, set a field:
change it, if it exists
add it, if it doesn't
What I do:
// fresh data
print_r(iterator_to_array($collection->find()->limit(2)));
// query
$docs = $collection->find()->limit(2);
// fetch
foreach ( $docs AS $id => $doc ) {
// update
$collection->update(array('_id' => $doc['_id']), array(
'$set' => array(
'existing_field' => 'x',
'new_field' => 'y',
),
), array('multiple' => false));
}
// verify
print_r(iterator_to_array($collection->find()->limit(2)));
Why doesn't that do anything? The existing field isn't changed and the new field isn't added. Is the condition maybe wrong??
PS. The full code (with a lot of junk in between): http://pastebin.com/CNfCVxex
lines 33 - 37 -- fresh data
lines 63 - 76 -- query, fetch & update
lines 79 - 80 -- verify
Not familiar with the driver you are using here, but from your description you can achieve what you want in a single database hit, no need to fetch/loop/update..
The $set operator will insert or update a field depending on whether it exists or not.
db.Collection.update({}, { $set : { "myfield" : "x" } }, false, true)
The above would set the 'myfield' field in all documents in the collection to 'x', or if it already exists it would change the value to 'x'. Is that what you want to achieve?
I suspect you need to convert the string $doc['_id'] back to a MongoId by using new MongoId. See the example at the bottom of this page: http://www.php.net/manual/en/class.mongoid.php