【问题标题】:Datomic: How do I query across any number of database inside of a query?Datomic:如何在查询中查询任意数量的数据库?
【发布时间】:2015-10-17 00:27:45
【问题描述】:

我正在使用 Datomic,并希望根据我的查询从任意数量的时间点提取整个实体。如果我在执行查询之前知道这些实例,Datomic 文档有一些关于如何从两个不同的数据库实例执行查询的不错示例。但是,我希望我的查询确定我需要的“as-of”类型数据库实例的数量,然后在提取实体时使用这些实例。到目前为止,这是我所拥有的:

(defn pull-entities-at-change-points [entity-id]
  (->>
    (d/q
      '[:find ?tx (pull ?dbs ?client [*])
        :in $ [?dbs ...] ?client
        :where
        [?client ?attr-id ?value ?tx true]
        [(datomic.api/ident $ ?attr-id) ?attr]
        [(contains? #{:client/attr1 :client/attr2 :client/attr3} ?attr)]
        [(datomic.api/tx->t ?tx) ?t]
        [?tx :db/txInstant ?inst]]
      (d/history (d/db db/conn))
      (map #(d/as-of (d/db db/conn) %) [1009 1018])
      entity-id)
    (sort-by first)))

我正在尝试查找其中 :client 实体上的某些属性发生更改的所有事务,然后将实体拉出,因为它在这些时间点存在。这条线:(map #(d/as-of (d/db db/conn) %) [1009 1018]) 是我尝试在两个特定事务中创建一系列数据库实例,我知道客户端的属性发生了变化。理想情况下,我想在一个查询中完成所有这些操作,但我不确定这是否可能。

希望这是有道理的,但如果您需要更多详细信息,请告诉我。

【问题讨论】:

    标签: clojure jvm datomic datalog


    【解决方案1】:

    我会将拉取调用拆分为单独的 API 调用,而不是在查询中使用它们。我会将查询本身限制为获取感兴趣的交易。解决此问题的一个示例解决方案是:

    (defn pull-entities-at-change-points
      [db eid]
      (let 
        [hdb (d/history db)
         txs (d/q '[:find [?tx ...]
                    :in $ [?attr ...] ?eid
                    :where
                    [?eid ?attr _ ?tx true]]
                  hdb
                  [:person/firstName :person/friends]
                  eid)
          as-of-dbs (map #(d/as-of db %) txs)
         pull-w-t (fn [as-of-db]
                    [(d/as-of-t as-of-db)
                     (d/pull as-of-db '[*] eid)])]
        (map pull-w-t as-of-dbs)))
    

    这个针对我用玩具模式构建的数据库的函数将返回如下结果:

    ([1010
      {:db/id 17592186045418
       :person/firstName "Gerry"
       :person/friends [{:db/id 17592186045419} {:db/id 17592186045420}]}]
     [1001
      {:db/id 17592186045418
       :person/firstName "Jerry"
       :person/friends [{:db/id 17592186045419} {:db/id 17592186045420}]}])
    

    我会评论几点:

    • 上面的函数采用a database value,而不是从环境/全局连接中获取数据库。
    • 我们为每个不同的时间 t 映射 pull。
    • using the pull API 作为入口点而不是查询适用于我们手头有实体和其他信息并且只需要属性或遍历引用的情况。
    • 在一个大查询中完成所有事情的动力在 Datomic 中并不真正存在,因为相关段将在对等体的缓存中实现。您不会,即使用一个查询来节省往返行程。
    • 集合绑定表单is preferred 超过containsleverages query caching

    【讨论】:

    • 感谢您的回复。这很有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 2014-09-03
    相关资源
    最近更新 更多