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))
如果我想检索具有N个属性的实体,我会让它们在每个查询中列出它们,这对我来说似乎很乏味且容易出错。
如何告诉Datomic检索包含所有字段的实体,而不必明确指定它们?
答案 0 :(得分:17)
从查询中获取实体(id):
=> (def eid (d/q '[:find ?e :where [?e :myapp/name "Fred"]] (db conn)))
你可以获得EntityMap:
=> (def ent (d/entity (db conn) (ffirst eid)))
因此您无需进行其他查询即可访问字段/属性:
=> (seq ent)
;; ([:myapp/name "Fred"] [:myapp/age 16] [:myapp/email "fred@email.com"])
然而,首先获得密钥可能更容易:
=> (keys ent)
;; (:myapp/name :myapp/age :myapp/email)
您甚至可以使用以下技巧获取反向键(指向此实体的“外部”ref属性):
=> (.touch ent)
=> (keys (.cache ent))
答案 1 :(得分:8)
您可以使用pull
从实体获取所有字段,甚至只是选择。使用'[*]
作为pull的模式将检索所有字段
有关详细信息,请参阅the pull documentation。
要从ID为eid
的实体获取所有字段,请使用:
(d/pull (db conn) '[*] eid)
Pull也可用于查询:
(datomic.api/q '[:find (pull ?e [*])
:where
[?e :myapp/name]
(db conn))
答案 2 :(得分:7)
datomic.api/entity提供了此类功能。
它只是有一个问题,即返回的地图有一个自定义表示,隐藏除:db/id
之外的所有字段。可以访问这些字段,但打印它们需要将地图合并到常规的Clojure地图中。
答案 3 :(得分:7)
只有" Touch" 该实体的所有属性都有一个特定的datomic.api/touch功能。 Entity函数返回的entity是惰性的,只有在访问时才返回属性值,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}
答案 4 :(得分:1)
我还没有测试过,但如果我没记错的话,你可以把一个变量作为属性名称
(datomic.api/q '[:find ?key ?value
:where
[?e ?key ?value]]
(db conn))