首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Om的查询->ast和ast->查询函数

Om的查询->ast和ast->查询函数
EN

Stack Overflow用户
提问于 2016-02-27 21:38:48
回答 2查看 555关注 0票数 6

根据Om Next文档

查询->ast (om.next/query->ast '(:foo {:bar 1})) 给定查询表达式,返回AST。 ast->查询 (om.next/ast->query ) 给定查询表达式AST,将其解析为查询表达式。

问题:为什么需要这些功能?也就是说,为什么需要直接操作om中的查询抽象语法树(我假设它是表示查询树的clojure映射以及一些元数据)?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-28 09:26:45

在某些情况下,需要直接操作查询广播。在远程解析模式下,解析器希望您的读取函数返回{: remote -name true }或(可能修改的) {:remote-name AST-node} (在env中以:ast的形式出现)。通常,您必须修改AST以重新构造它或添加一些数据。

示例1:您有一个查询:[{:widget {:list [:name :created]}}] :widget部件是纯UI相关的,您的服务器不需要知道它的存在,它只关心/知道:list。基本上,您必须修改解析器中的AST:

代码语言:javascript
运行
复制
(defmethod read :list
  [{:keys [ast query state]} key _ ]
  (let [st @state]
    {:value (om/db->tree query (get st key) st)
     :remote (assoc ast :query-root true)}))

如果在发送函数中使用om/process-roots,它将从ast中提取:query-root并将查询从[{:widget {:list [:name :created]}}]重写为[{:list [:name :created]}]

示例2:另一个示例是当您想在远程上更改某些内容时:

代码语言:javascript
运行
复制
(defmethod mutate 'item/update
  [{:keys [state ast]} key {:keys [id title]}]
  {:remote (assoc ast :params {:data {:id id :title title })})

在这里,您需要显式地告诉Om将您想要发送到AST中的数据包括进来。在您的遥控器上,您可以将:data拆分为更新给定id下的标题。

大多数情况下,您不会直接使用您在问题中描述的函数。解析器的每个方法中可用的env中都有ast

票数 7
EN

Stack Overflow用户

发布于 2016-10-22 00:21:10

当我试图使用Compassus的时候,我偶然发现了一些东西:

假设您有一个复杂的联合/连接查询,其中包含参数子查询。就像这样:

代码语言:javascript
运行
复制
`[({:foo/info
        {:foo/header [:foo-id :name]
        :foo/details [:id :description :title]}} {:foo-id ~'?foo-id
                                                  :foo-desc ~'?foo-desc})]

现在,假设您希望设置参数,以便在服务器上使用om/解析器解析它,并将这些参数视为read分派的第三个参数。当然,可以编写一个函数,该函数将在查询中找到所有必要的参数并设置值。但这并不容易,就像我说的--想象一下您的查询可能相当复杂。

所以,您可以做的是修改ast,ast包括:children :params键。因此,假设:foo-id:foo-desc的实际值处于:route-params键下的状态原子中:

代码语言:javascript
运行
复制
(defn set-ast-params [children params]
  "traverses given vector of `children' in an AST and sets `params`"
  (mapv
    (fn [c]
      (let [ks (clojure.set/intersection (-> params keys set) 
                                         (-> c :params keys set))]
        (update-in c [:params] #(merge % (select-keys params (vec ks))))))
    children))

(defmethod readf :foo/info
  [{:keys [state query ast] :as env} k params]
  (let [{:keys [route-params] :as st} @state
        ast' (-> ast 
                 (update :children #(set-ast-params % route-params))
                 om/ast->query
                 om.next.impl.parser/expr->ast)]
    {:value  (get st k)
    :remote ast'}))

所以基本上你是:-抓取,用你想的实际值修改它,也许你可以马上把它发送到服务器。唉,不!还没。问题是,当您执行{:remote ast}时,Om将:query部分提取出来,并将其组成,然后将其发送到服务器。因此,您实际上需要:将修改后的ast转换为query,然后再将其转换回ast。

备注:

  • 本例中的set-ast-params函数只适用于第一级(如果您有嵌套的参数化查询--它不能工作),使它是递归的--这并不困难
  • 有两种不同的方法可以将ast转换为查询,反之亦然: (om/ ast -> query ) ;;从ast检索查询并设置基于:params的参数;;它修改查询,;;如果您有一个联接查询,它只需要其中的第一项。例如:[({:foo/foo :id :bar/bar :id} {:id ~'?id})] ;;将丢失其:bar部件(om.next.Im.parer/ ast ->expr);从ast检索查询;但不根据ast的:params键设置查询解析。;;还有(om/query->ast) ;;和(om.next.Im.解析器/expr>ast)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35675766

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档