标题说明了一切,但是说我有一个简单的查询如下:
(q '[:find ?c ?n :where [?c :my-thing/its-attribute ?n]]
(d/db conn))
针对类似
的架构[{:db/id (d/tempid :db.part/db)
:db/ident :my-thing/its-attribute
:db/valueType :db.type/string
:db/doc "My thing's attribute"
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}]
如果查询匹配所有内容(例如,100M条目),则返回的结果将很大。如果我只想要其中一些,那么最好的方法是什么?
答案 0 :(得分:5)
两个随机名称使用rand(重复容忍)和样本(仅限不同)
(d/q '[:find [(rand 2 ?name) (sample 2 ?name)]
:where [_ :artist/name ?name]]
db)
此示例来自day-of-datomic github repo。
答案 1 :(得分:4)
对于"所有属性和值对的简单情况,排序",使用with seek-datoms
是最佳选择。以下示例使用mbrainz示例数据库:
var pcnt = (this.y / (chartt.series[0].yData + chartt.series[1].yData) * 100);
并返回:
(def conn (d/connect "datomic:sql://mbrainz-1968-1973?jdbc:postgresql://localhost:5432/datomic?user=datomic&password=datomic"))
(->> (d/seek-datoms (d/db conn) :avet :artist/sortName "Bea")
(take 20))
当然,您可以映射一个用于美化输出的fn或添加更多属性等,例如在此示例中:
(#datom[17592186050196 81 "Beach Boys, The" 13194139539089 true]
#datom[17592186047857 81 "Beatles, The" 13194139536749 true]
#datom[17592186048553 81 "Beau Brummels, The" 13194139537425 true]
#datom[17592186049043 81 "Beaver & Krause" 13194139537919 true]
#datom[17592186046205 81 "Beaver, Paul" 13194139535085 true]
#datom[17592186046692 81 "Beck, Bogert & Appice" 13194139535579 true]
#datom[17592186046886 81 "Beck, Jeff" 13194139535761 true]
#datom[17592186047111 81 "Beck, Jeff Group" 13194139535995 true]
#datom[17592186046486 81 "Bedford, David" 13194139535371 true]
#datom[17592186046992 81 "Bee Gees" 13194139535865 true]
#datom[17592186045876 81 "Beethoven, Ludwig van" 13194139534747 true]
#datom[17592186048427 81 "Beggars Opera" 13194139537321 true]
#datom[17592186047091 81 "Beginning of the End, The" 13194139535969 true]
#datom[17592186045945 81 "Belafonte, Harry" 13194139534825 true]
#datom[17592186047485 81 "Bell, Archie & Drells, The" 13194139536359 true]
#datom[17592186045915 81 "Bell, Carey" 13194139534799 true]
#datom[17592186046324 81 "Bell, Vinnie" 13194139535215 true]
#datom[17592186047164 81 "Bell, William" 13194139536047 true]
#datom[17592186047652 81 "Belle, Marie-Paule" 13194139536541 true]
#datom[17592186046496 81 "Bellou, Sotiria" 13194139535371 true])
返回:
(let [db (d/db conn)]
(->> (d/seek-datoms db :avet :artist/sortName "Bea")
(take 20)
(map #(merge {:artist/name (:v %)
:artist/type (-> (d/pull db [{:artist/type [:db/ident]}] (:e %))
:artist/type
:db/ident)}))))
注意:要将
({:artist/name "Beach Boys, The" :artist/type :artist.type/group}
{:artist/name "Beatles, The" :artist/type :artist.type/group}
{:artist/name "Beau Brummels, The" :artist/type :artist.type/group}
{:artist/name "Beaver & Krause" :artist/type :artist.type/group}
{:artist/name "Beaver, Paul" :artist/type :artist.type/person}
{:artist/name "Beck, Bogert & Appice" :artist/type :artist.type/group}
{:artist/name "Beck, Jeff" :artist/type :artist.type/person}
{:artist/name "Beck, Jeff Group" :artist/type :artist.type/group}
{:artist/name "Bedford, David" :artist/type :artist.type/person}
{:artist/name "Bee Gees" :artist/type :artist.type/group}
{:artist/name "Beethoven, Ludwig van" :artist/type :artist.type/person}
{:artist/name "Beggars Opera" :artist/type :artist.type/group}
{:artist/name "Beginning of the End, The" :artist/type :artist.type/group}
{:artist/name "Belafonte, Harry" :artist/type :artist.type/person}
{:artist/name "Bell, Archie & Drells, The" :artist/type :artist.type/group}
{:artist/name "Bell, Carey" :artist/type :artist.type/person}
{:artist/name "Bell, Vinnie" :artist/type :artist.type/person}
{:artist/name "Bell, William" :artist/type :artist.type/person}
{:artist/name "Belle, Marie-Paule" :artist/type :artist.type/person}
{:artist/name "Bellou, Sotiria" :artist/type :artist.type/person})
或seek-datoms
与datoms
一起使用,必须将相关属性编入索引。
答案 2 :(得分:1)
您是否尝试过使用get-some
?
来自:http://docs.datomic.com/query.html
GET-一些
get-some函数接受数据库,实体和一个或多个 基数 - 一个属性,返回实体id和的元组 实体拥有的第一个属性的值。
[(get-some $ ?person :person/customer-id :person/email) ?identifier]
- 编辑以回复评论 -
您还可以尝试创建一个选择低于特定数字的实体的查询。
user> (defn example-take-query [n]
(into '[:find ?e :where [?e :age ?a]]
[[`(~'> ~n ~'?e)]]))
#'user/example-take-query
user> (example-take-query 3)
[:find ?e :where [?e :age ?a] [(> 3 ?e)]]
user> (example-take-query 10)
[:find ?e :where [?e :age ?a] [(> 10 ?e)]]
答案 3 :(得分:1)
这个答案有点像@adamneilson的汇编以及对原始问题的评论。我试图完成与OP相同的事情,但是我不能在这里找到答案,所以希望这对某人有所帮助。
我的用例是用分页来获取100k记录。简单地使用take
/ drop
是绝对不可行的,因为它需要很长时间(几十秒)。
我的解决方法是首先获取所需的实体ID,对该集合执行take
/ drop
,然后使用entity
对其进行映射。这是我的最终代码:
(defn eid->entity
[eid]
(into {} (d/touch (d/entity (d/db (get-conn)) eid))))
(defn find-eids
[attr value limit offset]
(let [query '[:find ?eid
:in $ ?attr ?value
:where [?eid ?attr ?value]]
db (d/db (get-conn))
result (drop offset (sort (d/q query db attr value)))]
(map first (take limit result))))
(map eid->entity (find-eids :attr-name "value" 10 10)
这对我训练有素的大脑感觉非常错误,但我认为这是数据方式。并且它的速度并不是非常慢 - 对于10万条记录大约500毫秒,这对我来说已经足够了。
答案 4 :(得分:1)
在使用查询映射时,可以使用键:limit来实现SQL“ limit”子句的等效功能。
(d/q {:query '[:find ?c ?n :where [?c :my-thing/its-attribute ?n]]
:offset 1
:limit 10
:args [(d/db conn)]})
您可以在datomic客户端api文档中阅读有关此内容的更多信息:
https://docs.datomic.com/client-api/datomic.client.api.html
或关于查询映射语法:
答案 5 :(得分:0)
我有一个类似的需求,一段时间后为一个集合组合了SystemUser
的clojure MySql 方法:
context.SystemUsers.Select(u => new SystemUser
{
Username = u.Username,
Type = u.Type
});
repl的简单示例用法:
LIMIT
不确定它是否完全回答了您的问题,但可能会有所帮助。