我无法让第二级联接正常工作。为了简单起见,我在这里省略了一些事情。
我的根组件是:
(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))))
我的查询组成正确,初始数据正确规范化。我不会显示标准化数据,而且总查询还有更多。
(prn (om/get-query RootView)) =>
[{:list/events
[:id
{:body [:id :text :headline]}
{:media [:id :url :caption :credit]}
{:start-date [:id :year :month :day]}]}]
如果我通过解析器运行包含连接的查询,我得到:
(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]}]}
因此调用:list / events的read函数并返回它的数据,尽管所有第二个连接:body,:media和:start-date都没有。
我的阅读功能如下,第二个是未调用的功能。我遗漏了多方法:媒体和:开始日期,它们也没有被调用。我不确定这是什么症状。
(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})
在AST中正确识别连接(因此我假设查询语法是正确的)并且调度键与多方法的匹配。
(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}]}]}]}
我无法理解为什么解析器或其他东西(?)在第二次连接时停止?至于我有限的理解,至少应该调用身体上的多方法吗?
答案 0 :(得分:1)
所以我遇到的问题是理解我认为,Om Slack频道中的AntónioMonteiro建议我使用db->tree
函数。在:list/events
多方法中使用它,让它返回整个非规范化数据树。
答案 1 :(得分:0)
您必须自己从读取中进行递归,即在正在检查的键内的查询上调用解析器。 db->tree
为您完成此操作。事实上,每个read
调用db->tree
并不常见,因此看起来几乎相同。事实上,由于这个Untangled完全取消了这些读取。在这种情况下,你真的不需要自己做递归!
这里没有递归:
(into [] (map #(get-in st %)) (get st key))
get
上的任何key
都是默认数据库格式数据(应用数据)的引用部分。所以这里将由(get st key)
返回一系列的标识。任何get-in
都是app数据的表部分,因此返回实际数据值。 (map #(get-in st %))
是为每个身份执行此操作的换能器。但是数据的表部分是一个递归数据结构 - 必须是缺乏重复 - 所以任何不是'叶'数据的数据都由一个ident表示。所以这就是你要回来的东西 - 任何一个层次的东西,其他任何东西。
如果不了解默认数据库格式 - refs
和tables
部分,这个答案将毫无意义。到目前为止,我发现的最佳解释是here
此数据(st
)采用默认数据库格式:
{ :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]}}}
无论您在何处看到by-id
,都可以将密钥放在 tables mapentry中。正如您所看到的,(get-in st [:people/by-id 1])
结构将为您检索一个真实数据的地图,当然只有一个深度。
此处:list/people
是一个关键值,其中关联值是idents的向量。 (get st :list/people)
将为您提供此向量。此mapentry是st
的 refs 部分。