2012-06-12 19 views
6

Ich habe das Gefühl, dass ich alles falsch mache. Aber wie auch immer.Neo4j prüfen, ob der Knoten vor dem Erstellen vorhanden ist?

Ich habe eine SQL-Datenbank, die im Wesentlichen eine absichtlich denormalisierte Tabelle hat, die ich konstruiert habe, um diese Aufgabe für mich einfacher zu machen, also kann ich Sachen von einem Tisch gerade ergreifen.

Was ich habe, ist eine Tabelle von Paaren, etwa so:

user_lo | user_hi | something_else | other stuff 
1000 | 1234 | 1231251654  | 123 
1050 | 1100 | 1564654  | 45648 
1080 | 1234 | 456444894648 | 1 

Und so weiter.

Also für meine neo4j Graph db, ich möchte jede Benutzer-ID als Knoten, das andere Zeug ist nicht so wichtig, aber wird das Zeug in den Beziehungen im Grunde sein.

Ich möchte nur einen Knoten für jeden Benutzer, so mein Gefühl ist, dass, wenn ich so etwas tun:

while (rs.next()) { 
    node_lo = db.createNode(); 
    node_lo.setProperty("user_id", rs.getInt(1)); 
    node_hi = db.createNode(); 
    node_hi.setProperty("user_id", rs.getInt(2)); 
} 

dass, wenn wir den Knoten mit User_id 1234 zum zweiten Mal hinzufügen, wird es einfach erstellen ein neuer Knoten, aber ich, was ich will, ist es für diesen Knoten nur greifen, anstatt es zu erstellen, so dass ich es in diesem Fall zu der Beziehung zu 1080 hinzufügen kann.

Also was ist der Weg, dies zu tun?

Antwort

2

Haben Sie sich CREATE UNIQUE angesehen? Wenn Sie Cypher nicht verwenden können, können Sie unique nodes verwenden?

+0

bekommen oder erstellen Fabrik funktioniert gut, danke. –

4

Verwenden Sie einen Index zu suchen, und wenn kein Ergebnis gefunden, erstellen Sie einen neuen.

Index<Node> userIndex = graphDatabaseService.index().forNodes('UserNodes'); 

IndexHits<Node> userNodes = userIndex.get('id', 1234); 

if(!userNodes.hasNext()){ 
    //Create new User node 
} else { 
    Node userNode = userNodes.next(); 
} 

Ist das die Art von Operation, die Sie suchen?

+0

Das könnte funktionieren. Ist das schneller oder langsamer oder ist es das selbe wie die Methode get oder ccreate von Andres? Es sieht so aus, als würden sie auf unterschiedliche Weise dasselbe tun, aber ich verstehe nicht wirklich, wie Indizes in neo4j funktionieren. –

+0

Ich würde mir vorstellen, dass die Indizierung schneller wäre, da Indizierung normalerweise für schnelles Nachschlagen gedacht ist. – Nicholas

+0

Ich weiß nicht, ob ich die Dokumente falsch lese, aber bekomme oder erstelle keinen Index? Ich bin verwirrt. –

2

Sie werden wahrscheinlich die von Neo4j zur Verfügung gestellte UniqueNodeFactory verwenden möchten.

public Node getOrCreateUserWithUniqueFactory(String username, GraphDatabaseService graphDb) 
{ 
    UniqueFactory<Node> factory = new UniqueFactory.UniqueNodeFactory(graphDb, "UserNodes") 
    { 
     @Override 
     protected void initialize(Node created, Map<String, Object> properties) 
     { 
      created.setProperty("id", properties.get("id")); 
     } 
    }; 

    return factory.getOrCreate("id", id); 
} 
1

Normalisieren Sie Ihre SQL-Tabellen so, dass sie wie Knoten und Beziehungen aussehen. Dann mit Chiffre in der Migration können Sie die Migration rerunnable durch etwas machen wie

start a = node:node_auto_index('id:"<PK_Value>"') 
delete a 

create a = {id: "<PK_VALUE>", etc} 

für Knoten und da Sie in Ihrer many-to-many Mitte Tabelle haben sollen:

start LHS = node:node_auto_index('id:"<LHS_PK>"'), 
     RHS = node:node_auto_index('id:"<RHS_PK>"') 
create unique LHS=[:<relType> {<rel props>}]->RHS 

jetzt Sie werden am Ende ohne Duplikate und kann so oft wiederholen, wie Sie möchten.

0

Chiffre Abfrage verwenden, können Sie einen eindeutigen Knoten mit folgenden Syntax erstellen,

CYPHER 2.0 merge (x:node_auto_index{id:1}) 

wenn ein REST-Anruf tätigen, kann man Batch-Insertion wie

$lsNodes[] = array(

      'method'=> 'POST', 'to'=> '/cypher', 

      'body' => array(
       'query' => 'CYPHER 2.0 merge (x:node_auto_index{id_item:{id}})', 
       'params' => array('id'=>1) 
      ), 
      'id'=>0 

     ); 

     $sData = json_encode($lsNodes); 

in ähnlicher Weise für die Schaffung Beziehungen machen in eine Batch-Anfrage, gehen Sie wie folgt vor:

$lsNodes[] = array(

         'method'=> 'POST', 'to'=> '/cypher', 

         'body' => array(
          'query'  => 'start a=node:node_auto_index(id={id1}), b = node:node_auto_index(id={id2}) create unique a-[:have{property:30}}]-b;', 
          'params' => array(
           'id1' => 1, 'id2'=> 2 
          ) 
         ), 
         'id' => 0 

        ); 
$sData = json_encode($lsNodes); 
1

Verwenden Sie diese Funktion: Dabei gilt: ID ist der Schlüssel, den Sie überprüfen möchten, wenn er bereits existiert Typ: ist der Typ des Knotens (die Bezeichnung) Diese Funktion erstellt den Knoten und gibt ihn zurück, dann können Sie weitere Eigenschaften hinzufügen.

public static Node getOrCreateUserWithUniqueFactory(long ID, GraphDatabaseService graphDb, String Type) 
{ 
    UniqueFactory<Node> factory = new UniqueFactory.UniqueNodeFactory(graphDb, Type) 
    { 
     @Override 
     protected void initialize(Node created, Map<String, Object> properties) 
     { 

      created.addLabel(DynamicLabel.label(Type)); 
      created.setProperty("ID", properties.get("ID")); 
     } 
    }; 

    return factory.getOrCreate("ID", ID); 
} 
Verwandte Themen