2016-05-23 12 views
0

Ich schrieb einen einfachen Test, der gleichzeitig MERGE Anfragen ausführt und festgestellt, dass auf leere Datenbank mehr Knoten erstellt, obwohl ich eindeutige Knoten erwarten.Neo4j/Cypher gleichzeitig MERGE

[Test] 
    public void ConcurrentNodeMerge() 
    { 
     // act 
     Parallel.ForEach(Enumerable.Range(1, 10), index => 
     { 
      client.Cypher 
       .Merge("(n:Node)") 
       .Set("n.Index = COALESCE(n.Index, '') + ' ' + {index}") 
       .WithParam("index", index.ToString()) 
       .ExecuteWithoutResults(); 
     }); 

     // assert 
     var result = client.Cypher 
      .Match("(n:Node)") 
      .Return<string>("n.Index") 
      .Results; 

     Assert.That(result.Count(), Is.EqualTo(1)); 
    } 

ich am Ende immer wie mit zwei Knoten mit Indexfeld oben unter

Index 8 3 7 5 2 10 6 1 
Index 4 3 7 9 5 2 10 6 1 

Ich erwarte, dass einen Knoten, um mit neuestem Index ausgeführt.

Hinweis verwendet I .NET Neo4jClient

Antwort

2

Ich nehme an, Sie haben keine Einschränkung für die: Knoten (Index) Eigenschaft.

CREATE CONSTRAINT ON (n:Node) ASSERT n.Index IS UNIQUE; 

MERGE ist bedeutet nicht, Eindeutigkeit zu gewährleisten, ist es NUR mit einer einzigartigen Einschränkung gewährleistet.

1

Um zu erklären, warum Sie Duplikate erhalten: gleichzeitige MERGE blah Operationen zu einem race condition unterliegen, wobei jede Instanz der Operation feststellt, dass blah existiert noch nicht, jeder verursacht, vorwärts zu gehen und blah erstellen.

Die Art und Weise, diese Situation zu vermeiden, ist durch uniqueness constraints mit, wie @ChristopheWillemsen dargestellt.

+0

für zukünftige Leser Kenntnis nehmend, war das Rennen Bedingung ein Ergebnis eines Fehlers in einigen Neo4j Versionen (<3.0.9 für 3.0.x-Versionen und <3.1.2 für 3.1.x-Versionen) und fixiert, da wurde. Die Absicht war immer, Garantien zu sperren, damit MERGE keine doppelten Knoten erstellen konnte. – InverseFalcon