【问题标题】:Datomic Pull API only retrieves one entityDatomic Pull API 仅检索一个实体
【发布时间】:2015-07-12 23:45:45
【问题描述】:

我在搞清楚 pull API 时遇到了一些麻烦。我有两个位置实体。当我使用pull 时,我只收到一个。

(ns some-ns.core
  (:require [datomic.api :as d]))

(d/q '[:find ?e 
       :where [?e :location/name]]
     db)
=> #{[17592186045535] [17592186045420]} ; two results

(d/q '[:find [(pull ?e [:db/id
                        :location/name])]
       :where [?e :location/name]]
     db)
=> [{:db/id 17592186045535, :location/name "Some Other Location"}] ; one result

我怀疑我可能使用了不正确的 pull 表达式,但我没有发现明显的错误。

【问题讨论】:

    标签: clojure datomic


    【解决方案1】:

    我好像错过了...

    (d/q '[:find [(pull ?e [:db/id
                            :location/name]) ...]
           :where [?e :location/name]]
         db)
    => [{:db/id 17592186045535, :location/name "Some Other Location"} {:db/id 17592186045420, :location/name "White House"}]
    

    【讨论】:

    【解决方案2】:

    在您提供的示例中,您在 pull 表达式周围使用了“单元组”find specification,无论查询匹配的实体数量如何,它都只返回一个元组。如果你在 find 中指定了一个标量返回,你会遇到同样的问题,即使用.

    (1) 最直接的纠正方法是删除查找规范(这与您的原始查询的形式相匹配):

    (d/q '[:find (pull ?e [:db/id :location/name])
           :where [?e :location/name]]
         db)
    

    (2) 您也可以像您自己的回答一样,在 find 中指定一个集合:

    (d/q '[:find [(pull ?e [:db/id :location/name]) ...]
       :where [?e :location/name]]
     db)
    

    主要区别在于 (1) 将返回一组嵌套地图,而 (2) 将返回地图向量。

    【讨论】:

      【解决方案3】:

      为避免此类细微错误,您不妨试试the Tupelo Datomic library.

      Tupelo Datomic 没有使用“...”、“[]”等令人困惑的符号,而是将查询语法拆分为四个不同的函数。这是一个示例用法:

        ; If you want just a single attribute as output, you can get a set of values (rather than a set of
        ; tuples) using td/query-set.  As usual, any duplicate values will be discarded.
        (let [names     (td/query-set :let    [$ (live-db)]
                                      :find   [?name] ; <- a single attr-val output allows use of td/query-set
                                      :where  [ [?eid :person/name ?name] ] )
              cities    (td/query-set :let    [$ (live-db)]
                                      :find   [?loc]  ; <- a single attr-val output allows use of td/query-set
                                      :where  [ [?eid :location ?loc] ] )
      
        ]
          (is (= names    #{"Dr No" "James Bond" "M"} ))  ; all names are present, since unique
          (is (= cities   #{"Caribbean" "London"} )))     ; duplicate "London" discarded
      

      pull API is also supported 如果该格式更适合您的问题。尽情享受吧!

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-16
      • 2017-02-19
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 2012-06-13
      • 2019-01-24
      相关资源
      最近更新 更多