从Datomic实体获取所有字段

vem*_*emv 24 clojure datomic

Datomic Queries and Rules文档的"嵌入"部分说:

像SQL这样的查询语言是围绕客户端 - 服务器模型定义的,在单个对话中,您将需要同时执行以下操作:

  • 回答你的基本问题,例如本月买袜子的人.
  • 恢复报告和处理所需的任何其他信息,例如,他们的姓名和电子邮件地址.

后者实际上不是一个查询,它只是对相关信息的机械导航.

虽然我很欣赏这两个不同方面的正交性如何得到尊重,但我认为我经常需要检索整个实体,无论其属性如何.

据我所知,查询通常具有以下形式:

(datomic.api/q '[:find ?name ?age ?email
                 :where
                 [?e :myapp/name ?name]
                 [?e :myapp/age ?age]
                 [?e :myapp/email ?email]]
               (db conn))
Run Code Online (Sandbox Code Playgroud)

如果我想检索具有N个属性的实体,我会让它们在每个查询中列出它们,这对我来说似乎很乏味且容易出错.

如何告诉Datomic检索具有它们所持有的所有字段的实体,而不必明确指定它们?

Grz*_*ywo 18

从查询中获取实体(id):

=> (def eid (d/q '[:find ?e :where [?e :myapp/name "Fred"]] (db conn)))
Run Code Online (Sandbox Code Playgroud)

你可以得到EntityMap:

=> (def ent (d/entity (db conn) (ffirst eid)))
Run Code Online (Sandbox Code Playgroud)

这样您就可以访问字段/属性而无需进行其他查询:

=> (seq ent)
;; ([:myapp/name "Fred"] [:myapp/age 16] [:myapp/email "fred@email.com"])
Run Code Online (Sandbox Code Playgroud)

然而,首先获得密钥可能更容易:

=> (keys ent)
;; (:myapp/name :myapp/age :myapp/email)
Run Code Online (Sandbox Code Playgroud)

您甚至可以使用以下技巧获取反向键(指向此实体的"外部"ref属性):

=> (.touch ent)
=> (keys (.cache ent))
Run Code Online (Sandbox Code Playgroud)


Chr*_*lom 9

您可以使用pull从实体获取所有字段,甚至只是选择.使用'[*]pull作为模式将检索所有字段

有关更多信息,请参阅pull文档.

要从id eid使用的实体获取所有字段:

(d/pull (db conn) '[*] eid)

Pull也可用于查询:

(datomic.api/q '[:find (pull ?e [*])
                 :where
                 [?e :myapp/name]
               (db conn))
Run Code Online (Sandbox Code Playgroud)


小智 8

datomic.api /触摸功能

有一个特定的datomic.api/touch功能,只需"触摸"实体的所有属性. 实体由返回的实体功能是懒惰和只返回属性值访问时,该触摸功能急切地检索所有实体属性.

例:

(let [entity (d/entity db-val (ffirst (d/q '[:find ?e :in $ ?email
                                             :where [?e :user/email ?email]]
                                            db-val email))]
    ;;then just d/touch the entity returned by the d/entity fn
    (d/touch entity))
=> {:user/username "gretchen", :user/email "gretchen@user.com", :user/password "xxxxxx", :db/id 17592186046433}
Run Code Online (Sandbox Code Playgroud)


vem*_*emv 6

datomic.api/entity提供了这样的功能.

它只是有一个问题,即返回的地图有一个隐藏所有字段的自定义表示:db/id.可以访问这些字段,但打印它们需要将地图合并到常规的Clojure地图中.

  • 一些注意事项:(1)实体不"隐藏"属性,它们是获取实体属性和相关实体的惰性接口.从性能角度理解这一点非常重要,它解释了为什么属性并非全部立即可见 - 它必须从数据库中获取数据才能显示属性,从而挫败了懒惰的优势.(2)没有必要将实体合并到地图中 - 只需调用[touch](http://docs.datomic.com/clojure/#datomic.api/touch)函数即可获得所有属性. (2认同)