28

Datomic 查询和规则文档的“嵌入式”部分说:

像 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 检索具有它们持久化的所有字段的实体,而不必显式指定它们?

4

5 回答 5

20

从查询中获取实体(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)

您甚至可以使用以下技巧获取反向键(指向该实体的“外部”引用属性):

=> (.touch ent)
=> (keys (.cache ent))
于 2013-04-15T21:42:03.627 回答
14

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

有关更多信息,请参阅拉取文档

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

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

拉取也可以在查询中使用:

(datomic.api/q '[:find (pull ?e [*])
                 :where
                 [?e :myapp/name]
               (db conn))
于 2015-09-03T14:07:29.463 回答
10

datomic.api/touch函数

有一个特定的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}
于 2014-12-29T10:56:39.450 回答
7

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

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

于 2013-01-07T04:35:51.690 回答
0

我没有测试过,但如果我没记错的话,你可以把一个变量作为属性名

(datomic.api/q '[:find ?key ?value
             :where
             [?e ?key ?value]]
           (db conn))
于 2013-01-07T18:48:29.413 回答