【问题标题】:Datomic not returning the correct "min" result when retrieving entity ID in result tuple在结果元组中检索实体 ID 时,Datomic 未返回正确的“最小”结果
【发布时间】:2020-09-07 14:49:56
【问题描述】:

我有这个简单的架构和数据:

(def product-offer-schema
  [{:db/ident :product-offer/product
    :db/valueType :db.type/ref
    :db/cardinality :db.cardinality/one}
   {:db/ident :product-offer/vendor
    :db/valueType :db.type/ref
    :db/cardinality :db.cardinality/one}
   {:db/ident :product-offer/price
    :db/valueType :db.type/long
    :db/cardinality :db.cardinality/one}
   {:db/ident :product-offer/stock-quantity
    :db/valueType :db.type/long
    :db/cardinality :db.cardinality/one}
  ])
(d/transact conn product-offer-schema)

(d/transact conn
  [{:db/ident :vendor/Alice}
   {:db/ident :vendor/Bob}
   {:db/ident :product/BunnyBoots}
   {:db/ident :product/Gum}
  ])
(d/transact conn
  [{:product-offer/vendor  :vendor/Alice
    :product-offer/product :product/BunnyBoots
    :product-offer/price   9981 ;; $99.81
    :product-offer/stock-quantity 78
   }

   {:product-offer/vendor  :vendor/Alice
    :product-offer/product :product/Gum
    :product-offer/price   200 ;; $2.00
    :product-offer/stock-quantity 500
   }

   {:product-offer/vendor  :vendor/Bob
    :product-offer/product :product/BunnyBoots
    :product-offer/price   9000 ;; $90.00
    :product-offer/stock-quantity 15
   }
  ])

当我检索最便宜的兔子靴时,只检索价格,我得到预期的结果(9000):

(def cheapest-boots-q '[:find (min ?p) .
                        :where
                        [?e :product-offer/product :product/BunnyBoots]
                        [?e :product-offer/price ?p]
                       ])
(d/q cheapest-boots-q db)
;; => 9000

但是,当我想获取实体 ID 和价格时,它给了我价格更高的靴子:

(def db (d/db conn))
(def cheapest-boots-q '[:find [?e (min ?p)]
                        :where
                        [?e :product-offer/product :product/BunnyBoots]
                        [?e :product-offer/price ?p]
                       ])
(d/q cheapest-boots-q db)
;; => [17592186045423 9981]

我尝试添加 :with 但这给了我一个错误:

(def cheapest-boots-q '[:find [?e (min ?p)]
                        :with ?e
                        :where
                        [?e :product-offer/product :product/BunnyBoots]
                        [?e :product-offer/price ?p]
                       ])
(d/q cheapest-boots-q db)
;; => =>  Execution error (ArrayIndexOutOfBoundsException) at datomic.datalog/fn$project (datalog.clj:503).

我做错了什么?

【问题讨论】:

  • 对于它的价值,手册 (docs.datomic.com/cloud/query/query-data-reference.html) 说:“不在聚合表达式中的查询变量将对结果进行分组并在结果中完整显示。”此外,该页面上的示例没有将 find 变量装箱在向量中,并且 :with 被明确定义为不返回 with'd 变量。简而言之,请看一下手册。我不确定它是否能回答你的具体问题,但它有很多你可能感兴趣的东西。

标签: clojure datomic


【解决方案1】:

正如评论者所指出的那样,?e 不会以任何方式绑定到 (min ?p) 表达式,因此除了某种产品实体 ID 之外,它没有定义你会得到什么。

您真正想做的是以某种方式将这些值统一为查询的一部分,而不是对结果执行聚合,例如:

(d/q '[:find [?e ?p]
       :where
       [?e :product-offer/product :product/BunnyBoots]
       [?e :product-offer/price ?p]
       [(min ?p)]] 
     db)

您可以看到min 子句是查询的一部分,因此将参与结果的统一,给您想要的。

【讨论】:

    猜你喜欢
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多