2016-03-27 14 views
3

Ich habe Probleme bekommen eine zweite Ebene zu verbinden, um richtig zu arbeiten. Ich habe einige Dinge hier aus Gründen der Breathness weggelassen.Om Nächste lesen Multi-Fn nicht in der zweiten Ebene Join aufgerufen, Abfrage AST nicht vollständig geparst, daher Komponente nur Empfangen von IDs

Meine Stammkomponente ist:

(defui RootView 
    static om/IQuery 
    (query [this] 
    `[{:list/events ~(om/get-query Event)}]) 
    Object 
    (render [this] 
    (let [{:keys [list/events]} (om/props this)] 
     (events/event-list events)))) 

Meine Abfragen komponieren korrekt und die Anfangsdaten richtig normalisiert. Ich werde die normalisierten Daten nicht anzeigen, und die gesamte Abfrage enthält mehr.

(prn (om/get-query RootView)) => 

[{:list/events 
    [:id 
    {:body [:id :text :headline]} 
    {:media [:id :url :caption :credit]} 
    {:start-date [:id :year :month :day]}]}] 

Wenn ich eine Abfrage enthält, die Verbindungen durch einen Parser laufen erhalte ich:

(prn (parser {:state (atom norm-data)} 
     '[{:list/events 
      [:id 
      {:body [:id :text :headline]} 
      {:media [:id :url :caption :credit]} 
      {:start-date [:id :year :month :day]}]}])) => 

{:list/events 
[{:id 1, 
    :media [:media/by-id 1], 
    :start-date [:start-date/by-id 1], 
    :body [:body/by-id 1]} 
    {:id 17, 
    :media [:media/by-id 17], 
    :start-date [:start-date/by-id 17], 
    :body [:body/by-id 17]}]} 

So ist die Lesefunktion für: Liste/wird Ereignisse aufgerufen und gibt seine Daten, wenn alle der zweite schließt sich für : body,: media und: start-date sind nicht.

Meine Lesefunktionen sind wie folgt, die zweite ist die, die nicht aufgerufen wird. Ich habe die Multimethoden auf: Medien und: Start-Datum, sie werden auch nicht aufgerufen. Ich bin mir nicht sicher, was das für ein Symptom ist.

(defmulti read om/dispatch) 

(defmethod read :list/events 
    [{:keys [state] :as env} key params] 
    (let [st @state] 
    {:value (into [] (map #(get-in st %)) (get st key))})) 

(defmethod read :body 
    [{:keys [state query]} key _] 
    (println "This is never printed") 
    {:value :doesnt-matter}) 

Die Verbindung korrekt in dem AST identifiziert wird (so gehe ich davon aus der Abfrage Grammatik korrekt ist) und der Versand Schlüssel übereinstimmt, dass die Multi-Methode.

(prn (om/query->ast (om/get-query RootView))) => 

{:type :root, 
:children 
[{:type :join, 
    :dispatch-key :list/events, 
    :key :list/events, 
    :query 
    [:id 
    {:body [:id :text :headline]} 
    {:media [:id :url :caption :credit]} 
    {:start-date [:id :year :month :day]}], 
    :component timeline.components.events/Event, 
    :children 
    [{:type :prop, :dispatch-key :id, :key :id} 
    {:type :join, 
    :dispatch-key :body, 
    :key :body, 
    :query [:id :text :headline], 
    :component timeline.components.events/EventBody, 
    :children 
    [{:type :prop, :dispatch-key :id, :key :id} 
     {:type :prop, :dispatch-key :text, :key :text} 
     {:type :prop, :dispatch-key :headline, :key :headline}]}]}]} 

Ich kann nicht verstehen, warum der Parser oder etwas (?) Bei der zweiten Join stoppt? Soweit mein begrenztes Verständnis geht, sollte die Multi-Methode on: body zumindest aufgerufen werden?

Antwort

0

Sie müssen die Rekursion von innerhalb der Lesevorgänge selbst durchführen, d. H. Den Parser auf der Abfrage aufrufen, die sich innerhalb des geprüften Schlüssels befindet. db->tree macht das für Sie. In der Tat ist es nicht ungewöhnlich, dass jeder readdb->tree nennt und so ziemlich gleich aussieht. In der Tat wegen dieser Unentschiedenheit beseitigt diese liest überhaupt. In diesem Fall müssen Sie die Rekursion nicht wirklich selbst durchführen!

Es gibt keine Rekursion hier:

(into [] (map #(get-in st %)) (get st key)) 

Jede get auf einem key ist der Refs Teil der Standard db formatiert Daten (App-Daten). Hier wird also eine Reihe von IDs von (get st key) zurückgegeben. Any get-in ist zu den Tabellen Teil der App-Daten und gibt so echte Datenwerte zurück. (map #(get-in st %)) ist der Transducer, der dies für jeden Ident tut. Aber die Tabellen Teil der Daten ist eine rekursive Datenstruktur - muss für einen Mangel an Wiederholungen sein - so dass alle Daten, die nicht 'Blatt' Daten durch eine Ident dargestellt wird. Das ist es also, was du zurückbekommst - alles, was eine Ebene tief ist und sonst nichts andeutet.

Diese Antwort wird fast sinnlos ohne ein Verständnis des Standard-Datenbank-Format - die refs und tables Teile machen.Die beste Erklärung, die ich bisher gefunden habe ist here

Diese Daten (st) sind in Standard db Format:

{ :list/people [[:people/by-id 1] [:people/by-id 2] ... ] 
    :people/by-id { 1 { :db/id 1 :person/name "Joe" :person/mate [:people/by-id 2]} 
        2 { :db/id 2 :person/name "Sally" :person/mate [:people/by-id 1]}}} 

Wo auch immer Sie by-id sehen, dass ein weggeben ist, dass der Schlüssel in einem ist Tabellen Mapentry. Wie Sie an der Struktur sehen können (get-in st [:people/by-id 1]) wird für Sie eine Karte abrufen, die die echten Daten ist, natürlich nur auf einer Ebene tief.

Hier :list/people ist ein Schlüssel, wo der zugehörige Wert ein Vektor von Idents ist. (get st :list/people) wird Ihnen diesen Vektor geben. Diese Mapentry ist die Refs Teil von st.

+0

Mein Missverständnis war, wo die Rekursion passiert ist. Mein Gedanke war, dass der Parser auf den Join der zweiten Ebene stoßen und nach der relevanten Multi-Methode suchen würde, weshalb ich eine Multi-Methode für ': body' hatte. Also gegeben, was Sie sagen, Sie haben nur Multi-Methoden "lesen" für jede Top-Level-Taste, richtig? –

+0

Mein Verständnis ist, dass für die Schlüssel ganz unten brauchen Sie keine Lese-Methoden, aber für alle Ebenen höher Sie tun. In der Realität ist es nicht so schwierig, weil Sie eine Fehlermeldung erhalten und eine andere einlegen! –

+0

Ich verstehe das Standard-DB-Format und kann mit den zusammengesetzten 'IQuery'- und' Ident'-statischen Methoden korrekt de-normalisierte Daten in es hinein bekommen. Ich verstehe jetzt, dass ich den rekursiven Join innerhalb der "read" Multi-Methode der obersten Ebene machen muss und dass der Parser keine weiteren Multi-Methoden aufrufen wird. Angesichts dessen scheint es mir, dass Sie dann nur Lese-Multi-Methoden der obersten Ebene benötigen. Ich verstehe es also nicht, wenn du sagst "aber für alle höheren Stufen, die du tust". Es ist Zeit, die Quelle zu lesen, denke ich, hah! –

1

Also das Problem, das ich habe, ist ein Verständnis Ich denke, António Monteiro in der Om Slack-Kanal vorgeschlagen, dass ich die db->tree Funktion verwenden. Wenn Sie dies in der :list/events Multi-Methode verwenden, können wir den gesamten Baum der de-normalisierten Daten zurückgeben.