Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to create an edge in a transaction #72

Open
forty1 opened this issue May 13, 2016 · 13 comments
Open

How to create an edge in a transaction #72

forty1 opened this issue May 13, 2016 · 13 comments

Comments

@forty1
Copy link

forty1 commented May 13, 2016

I use PHP 5.5 and try to create an edge. I used the command function:

function createEdge($rIdVertex1, $rIdVertex2, $paramValue){
    $SQL = 'CREATE EDGE MyEdge'.
            ' FROM #'.$rIdVertex1->cluster.':'.$rIdVertex1->position.
            ' TO #'.$rIdVertex2->cluster.':'.$rIdVertex2->position.
            ' SET paramvalue='.$paramValue;
    return $this->dbclient->command($SQL);
}

It worked fine but now I need it in a transaction. My code looks like the next example:

$tx = $this->client->getTransactionStatement();
try{
            $tx = $tx->begin();
            $createCommand = $this->daoSimilarities->createEdge($recVertex1->getRid(), $recVertex2->getRid(), 0);
            $tx->attach($createCommand);
            $result = $tx->commit();
            ...
}catch( Exception $e){
            $tx->rollback();
            return self::getErrorResult(....);
}

But I get an error by using commands in a transaction (ERROR: Wrong command type PhpOrient\Protocols\Binary\Operations\Command).

I changed the type and used recordCreate.

function createEdge($rIdVertex1, $rIdVertex2, $paramValue){
    return $this->dbclient->recordCreate(
                (new Record())
                    ->setOData( ['paramvalue' => $paramValue, 'out' => $rIdVertex1, 'in' => $rIdVertex2] )
                    ->setOClass('MyEdge')
                    ->setRid(new ID($this->cluster))
            );
}

Finally my edge was created but only the edge had 'out' and 'in' parameters, not the verteces (vertex1, vertex2). If I use shortestPath of vertex1 and vertex2 it will not find any path. Does somebody has a solution for that problem?

@forty1 forty1 changed the title How to create a edge in a transaction How to create an edge in a transaction May 13, 2016
@forty1
Copy link
Author

forty1 commented May 20, 2016

I am sorry to ask it again but are there any solutions to create an egde in a transaction?

@smolinari
Copy link

Out of curiosity, but what leads you to believe you need a transaction to create an edge?

Scott

@andreyvk
Copy link

Makes sense to me. Sometimes a few records within a transaction could get connected. Besides, edge is also a record, if it's not a light edge. Therefore, any record should be able to be placed within a transaction

Sent from my iPhone

On May 20, 2016, at 23:02, Scott [email protected] wrote:

Out of curiosity, but what leads you to believe you need a transaction to create an edge?

Scott


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub

@smolinari
Copy link

Yes, if you are doing more than just creating an edge, you might want a transaction. But, isn't the creation of an edge atomic itself?

Scott

@forty1
Copy link
Author

forty1 commented May 23, 2016

Thanks for your response. The clue is, that it is not allowed to have two edges between two vertices.

Example: Users can vote the similarity between two movies. If there’s no connection, an edge (similarity) will be created. If one already exist, only the weight of the edge will be changed.

Finally I have to check if a direct path exist between the two specific movies, if not I create one. So how should I avoid that two user vote the same movies at the same time? Is it possible to adjust that only one similar edge exist? Lightweight Edge is not a solution for me because I have a property on my edge.

@smolinari
Copy link

smolinari commented May 23, 2016

Your domain problem sounds similar to another thread I was discussing in the ODB Google group and I believe your logic problem is similar. To find out if someone has already done a "vote" (or rating), one would have to know about the votes (or ratings). That means, the votes are an object and should be a vertex and not an edge. Once votes are a vertex, then thinking logically about them becomes much easier. Working with them also becomes easier in ODB, because you can use the unique index on the relationships (the edges) between the votes, the users and the movies. You can do a lot more with that data structure, than you can with trying to make an edge work like an object, which it isn't. An edge should only signify a relationship. This is the structure I'd suggest.

user <=voted=> similarity_vote <=similar_to=> movie1
.................................................<=similar_to=> movie2

So the logic is...

  1. Check to see if the vote is already made between two particular movies.
  2. If not, add vote and connect them with the 3 edges accordingly. And, that would require a transaction and we are back to your old problem.

Check out this test on how a transaction (sh)could be used.(?)

https://github.com/Ostico/PhpOrient/blob/master/tests/PhpOrient/TxCommitTest.php

Maybe it might help. 😄

Scott

@forty1
Copy link
Author

forty1 commented May 23, 2016

Thank you for the detailed answer and I am sorry if we lose the focus of the question.

I am open-minded for the structure and I had a similar one at the beginning. How do you select all similar movies of a reference movie for all user votes?
For the current structure queries would look like:

  • Get all similar movies by traverse query with a depth limitation
  • Get the shortest path with weight between the reference movie and selected movies

Example for current structure:
movie1 <= (0,5) => movie2 <= (0,4) => movie3 <= (0,5) => movie4
The similarity of the movies 1 and 4 is 10%, for example.

How do you find out the similarity of movie 1 and 4 at the new structure? Is the new structure right?

User1 <= (voted) => vote: 50% <= (similar_to) => movie1
............................. <= (similar_to) => movie2

..... <= (voted) => vote: 50% <= (similar_to) => movie3
............................. <= (similar_to) => movie4

User2 <= (voted) => vote: 40% <= (similar_to) => movie2
............................. <= (similar_to) => movie3

Maybe it will help me if you send me the link of the ODB Google group discussing?

@smolinari
Copy link

Naw, the discussion in GG is a bit different.

Now that you've explained a bit more, I understand your domain a bit better. I was under the impression, the votes had to be related to the users. If that isn't the case, then you are right. The relationship is the similarity and not the vote itself.

This will probably show my incompetence, but how did you come up with the 10% similarity in your example?

Scott

@forty1
Copy link
Author

forty1 commented May 23, 2016

Hey Scott. The calculation was:

movie1 - movie2: 100 *0,5 = 50%
movie1 - movie3: 50  *0,4 = 20%
movie1 - movie4: 20  *0,5 = 10%

Finally I still have the problem: how do I avoid that two user vote the same movies at the same time?
Transaction is the only way I know, but it doesn't work :(

@smolinari
Copy link

Ahhh! See, I knew I was on to something. If you need to know about the votes made between users, then you need the votes as vertices. If you need the calculation of the relationships to each movie, that is a different graph. I would assume, the votes also change the amount of the relationship? So, you need both.

movie <= similarity => movie

and

user <= voted => vote <= similar_to => movie1
----------------------------<= similar_to => movie2

Whether or not you can do the same calculation with only the lower graph, is beyond my own capabilities. Sorry....

Scott

@forty1
Copy link
Author

forty1 commented May 23, 2016

Hey Scott,

thank you for your advice and your help. I will think about it.
But I am thinking "similar" as andreyvk ;D There are plenty of reasons why an edge should be created in a transaction. You can even find one example in OrientDB documentation (http://orientdb.com/docs/2.1/Concurrency.html).

@smolinari
Copy link

Yes, I am not denying the edge in this case should be created in a transaction with the other tasks that need to get done.

Actually now digging into your code, what is $this->daoSimilarities? Because, theoretically, the returned value of your createEdge function should be the input to the attach method.

Scott

@dadagama
Copy link

i'm having the same issue trying to create a bunch of edges with transactions, so tried a workaround using sqlBatch approach:

  $cmd = 'BEGIN;';
  foreach ($edges as $edge) {
    $cmd .= 'CREATE EDGE myClass FROM ' . $edge['in'] . ' TO ' . $edge['out'] . ';';
  }
  $cmd .= 'COMMIT RETRY 100;';
  $this->client->sqlBatch( $cmd );

https://github.com/Ostico/PhpOrient#execute-orientdb-sql-batch
not sure if that has the same effect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants