问题描述
我有这个简单的架构和数据:
(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]
(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).
我在做什么错了?
解决方法
正如评论者所指出的那样,?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
子句是查询的一部分,因此将参与结果的统一,从而为您提供所需的内容。