首页 文章

从Datomic实体获取所有字段

提问于
浏览
22

Datomic Queries and Rules文件的'Embedded'部分说:

像SQL这样的查询语言是围绕客户端 - 服务器模型进行的,在单个对话中,您将同时使用这两种语言:回答您的基本问题,例如谁在本月买了袜子 . 恢复报告和处理所需的任何其他信息,例如他们的名字和电子邮件地址是什么 . 后者实际上不是一个查询,它只是对相关信息的机械导航 .

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

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

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

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

How to tell Datomic to retrieve the entities with all the fields they were persisted with, without having to specify them explicitly?

5 回答

  • 8

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

    您可以使用 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))
    
  • 7

    datomic.api/entity提供此类功能 .

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

  • 7

    datomic.api /触摸功能

    有一个特定的datomic.api/touch函数只是"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}
    
  • 1

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

    (datomic.api/q '[:find ?key ?value
                 :where
                 [?e ?key ?value]]
               (db conn))
    

相关问题