2016-04-01 4 views
1

Ich habe zwei Tage gesucht und habe keinen Code, der zu diesem geschlossen ist, gesehen. Dies ist der einzige Code in Java, den ich gesehen habe und es ist nicht genau das, was ich wollte.Aktualisierung der Transaktion in Datomic für ein Attribut, das viele Kardinalität hat

conn.transact(list(list("db.fn/cas", datomic_id, "attribute you want to update", old value, new value))).get(); 

Ich habe diesen Code mit einem einzigen Wert in dem alten Wert und ein einzigen Wert in dem neuen Wert versucht, aber es stapelt nur die Informationen, anstatt sie zu überlagern. Beispiel: alter Wert ist Huhn und neuer Wert ist Fisch. Nach der Transaktion ist es [Hühnchen, Fisch] anstelle von dem, was ich erwartet habe, nur [Fisch] und Huhn wird in Archiv (Geschichte) bewegt werden.

Die Frage ist also, wie Sie den alten Array-Wert angeben und wie geben Sie den neuen Wert ein Array, damit es aktualisiert wird, wie ich erwartet habe, wie oben angegeben.

Ich erinnere mich irgendwo zu lesen, dass unter der Haube nur eine Reihe von Werten zu einem Attribut verknüpft ist. Wenn dies der Fall ist, bedeutet das, dass ich die Datomic-ID der Zeichenfolge finden und ändern muss? Müssen Sie es auch entfernen, wenn es nicht in der neuen Liste ist?

Antwort

0

Wenn Sie eine "letzte Schreibweise" konsistente Lösung benötigen, um alle Werte für eine bestimmte Entität für eine Karte, die viele Attribute enthalten, zu ersetzen, ist Ihre beste Wette, mit einem transaction function zu gehen. Sie könnten folgendermaßen vorgehen:

  1. Erhalten Sie alle Daten, die übereinstimmende Entität + Attribut, für die Sie alle Werte zurückziehen möchten.
  2. Generieren Sie Rückzüge für alle von ihnen.
  3. erstellen Transaktionen für alle neuen Werte hinzuzufügen (zum Beispiel von einer übergebene Sammlung)
  4. Konflikte entfernen (das heißt, wenn Sie die gleiche EAV haben beide mit einem Add und Ergebnis)
  5. Return die daraus resultierenden Transaktionsdaten.
+0

Ich vermute, das würde zwei Transaktionen generieren. Eins, um den ganzen Wert zurückzuziehen und noch einen, um sie wieder hinzuzufügen? Ich ging einen anderen Weg zum Erstellen eines anderen Namespace mit dem Array dort. Auf diese Weise erstelle ich einfach einen neuen Namespace und ändere den Verweis auf diesen neuen Namespace. Ich weiß nicht, ob das schneller ist oder dein Weg schneller ist. – pompanoSlayer

+0

Sie generieren eine Transaktion ("Die resultierenden Transaktionsdaten zurückgeben"), indem Sie sich zwei Sammlungen von Daten ansehen (was ist dort und was möchten Sie dort sehen). Das ist gesagt, meine Schritte sind ausführlich und Sie könnten einfach das diff nach Inspektion über z. ziehen, was wahrscheinlich eine bessere Lösung ist. –

+0

Es scheint, als ob ich dem Datomic-Modell von Entitäten und Prädikaten folgen würde, dies würde mich zu Ihrer Lösung VS führen. Es wird unscharf, wenn ich andere Entitäten hinzufüge, um mit diesem Problem zu helfen. – pompanoSlayer

1

FYI, das sind die generischen Transaktionsfunktionen ich zur Zeit für diese Art von Aufgabe verwenden (von Clojure erklärt, sollten aber recht einfach zu Java anpassen falls erforderlich):

[{:db/ident :bsu.fns/replace-to-many-scalars, 
    :db/doc "Given an entity's lookup ref, a to-many (scalar) attribute, and a list of new values, 
yields a transaction that replaces the old values by new ones" 
    :db/id (d/tempid :db.part/user), 
    :db/fn (d/function 
      '{:lang :clojure, 
      :imports [], 
      :requires [[datomic.api :as d]], 
      :params [db entid attr new-vals], 
      :code (let [old-vals (if-let [e (d/entity db entid)] (get e attr)()) 
         to-remove (remove (set (seq new-vals)) old-vals)] 
        (concat 
         (for [ov to-remove] [:db/retract entid attr ov]) 
         (for [nv new-vals] [:db/add entid attr nv])) 
        )}), 
    } 
{:db/ident :bsu.fns/to-many-retract-all-but, 
    :db/doc "Given an entity lookup ref, a to-many (entity) attribute, and a list of lookup refs 
    expands to a transaction which will retract all the [origin `to-many-attr` target] relationships but those for which target is among the `to-spare-lookup-refs`" 
    :db/id (d/tempid :db.part/user), 
    :db/fn (d/function 
      '{:lang :clojure, 
      :imports [], 
      :requires [[datomic.api :as d]], 
      :params [db origin to-many-attr to-spare-lookup-refs], 
      :code (let [old-targets-ids (d/q '[:find [?t ...] :in $ ?to-many-attr ?origin :where [?origin ?to-many-attr ?t]] 
              db to-many-attr origin) 
         to-spare-ids (for [lr to-spare-lookup-refs] (:db/id (d/entity db lr))) 
         to-delete (->> old-targets-ids (remove (set to-spare-ids)))] 
        (for [eid to-delete] [:db/retract origin to-many-attr eid]) 
        #_[old-targets-ids to-update-ids to-delete])}), 
    }] 

I don‘ Ich behaupte überhaupt, sie sind optimale Leistung oder Design-weise, aber sie haben für mich bisher funktioniert. HTH.