tonsky / datascript

Immutable database and Datalog query engine for Clojure, ClojureScript and JS
Eclipse Public License 1.0
5.51k stars 308 forks source link

Reverse Lookups break transactions of deeply nested maps #182

Open Conaws opened 8 years ago

Conaws commented 8 years ago

In deeply nested maps, datascript can successfully build relationships with both the lookup ref, and reverse lookup ref, however, it seems like when you combine them, it does not create a connection

for example A -> B -> C ;; works C <- B <- A ;; works A -> C <- B ;; does not work

(deftest test-resolve-eid-refs-deep-map
  (let [conn (d/create-conn {:name {:db/unique :db.unique/identity}
                             :friend {:db/valueType :db.type/ref
                                      :db/cardinality :db.cardinality/many}})
        tx   (d/transact! conn [{:name "Sergey"
                                 :friend [{:name "Ivan"}
                                          {:name "Petr"}]}
                                {:name "Oleg"
                                 :friend [{:name "Dmitri"
                                           :friend [{:name "Sven"
                                                     :friend [{:name "John"
                                                               :friend [
                                                                        {:name "Sergey"}
                                                                        ]
                                                               :_friend [
                                                                         {:name "Dmitri"}]}
                                                              {:name "Petr"}]
                                                     }]}]
                                 :_friend [{:name "Boris"}]}]
                          )
        q '[:find ?fn
            :in $ ?n
            :where [?e :name ?n]
            [?e :friend ?fe]
            [?fe :name ?fn]]]
    (is (= (d/q q @conn "Sergey") #{["Ivan"] ["Petr"]}))
    ;; true
    (is (= (d/q q @conn "Boris") #{["Oleg"]}))
    ;; true
    ;; this shows that :_ does build relationship on reverse lookups  
    ;;  and can create the new entity at the same time
    (is (= (d/q q @conn "Oleg") #{["Dmitri"]}))
    ;; true
    (is (= (d/q q @conn "Sven") #{["John"][ "Petr"]} ))
    ;; true
    (is (= (d/pull @conn '[:name {:_friend 1}] [:name "Petr"])
           {:name "Petr"
            :_friend [{:name "Sergey"}
                      {:name "Sven"}]}))
    ;; true - shows that you can create relationships on a deep add, even to existing ents
    (is (= (d/q q @conn "Dmitri") #{["Sven"] ["John"]}))
    ;; fails, only Sven is a friend of Dmitri
    ;; shows that if you are going to be doing a deep map transaction, each path
    ;; needs to only go in one direction
    (is (= (d/q q @conn "John") #{["Sergey"]}))
    ;; true, shows that the deep add works when moving in one direction
    ))

Am I missing something?

Conaws commented 8 years ago

Any word on this? Pretty critical for something I'm building -- happy to help try to fix it if you've got any guidance.

tonsky commented 8 years ago

Sorry — I’m on vacation currently. If you’re eager to fix, you’ll probably have to look somewhere around https://github.com/tonsky/datascript/blob/d45ddf6e73a542e3bcf6e8845c0c21d2eea20f21/src/datascript/db.cljc#L934-L949

Also, I’m sure there’re plenty of ways to work arounds this. Just don’t use that particular combination, for example.

On Mon, Oct 24, 2016 at 12:42 AM Conor White-Sullivan < notifications@github.com> wrote:

Any word on this? Pretty critical for something I'm building -- happy to help try to fix it if you've got any guidance.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/tonsky/datascript/issues/182#issuecomment-255619948, or mute the thread https://github.com/notifications/unsubscribe-auth/AARabJWEAsuWUmhPpQlq7Ov-b3X_oocxks5q2-LLgaJpZM4KLveC .