假设我的后端有一百万个文章实体,其中 inst 属性名为 date ,或者一百万播放器具有 int 属性的实体,名为 points 。选择10篇最新文章或得分最高的球员有什么好方法?
我是否需要将全部数百万的内容提取给对等方,然后对它们进行排序和删除?
答案 0 :(得分:2)
在掌握反向索引becomes a Datomic feature之前,您可以手动定义一个。
e.g。对于:db.type / instant,创建一个类型的附加属性:db.type / long,您将填充
(- (Long/MAX_VALUE) (.getTime date))
可以使用
获取最新的10篇文章(take 10 (d/index-range db reverse-attr nil nil))
答案 1 :(得分:1)
是的,您需要获取所有数据,因为没有可以帮助您的索引。
我会创建自己的“索引”并规范化这些数据。您可以拥有一组单独的N个实体,您可以根据需要保留多个实体。您可以从10开始,或考虑存储100以交换一些(可能可忽略的)速度以获得更大的灵活性。此索引可以存储在您作为模式的一部分添加的单独“单例”实体中。
;; The attribute that stores the index
{:db/id #db/id[:db.part/db]
:db/ident :indexed-articles
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many
:db.install/_attribute :db.part/db}
;; The named index entity.
{:db/id #db/id[:db.part/db]
:db/ident :articles-index}
您可以拥有执行此操作的数据库功能。每次插入要“索引”的新实体时,请调用此函数。
[[:db/add tempid :article/title "Foo]
[:db/add tempid :article/date ....]
[:index-article tempid 10]]
index-article的实现可能如下所示:
{:db/id #db/id[:db.part/user]
:db/ident :index-article
:db/fn #db/fn {:lang "clojure"
:params [db article-id idx-size]
:code (concat
(map
(fn [article]
[:db/retract
(d/entid db :articles-index)
:indexed-articles
(:db/id article)])
(->> (datomic.api/entity db :articles-index)
(sort-by (fn [] ... implement me ... ))
(drop (dec idx-size))))
[[:db/add (d/entid db :articles-index) :indexed-articles article-id]])}}
免责声明:我实际上没有测试过这个函数,所以它可能包含错误:)一般的想法是我们从集合中删除任何“溢出”实体,并添加新的实体。当idx-size为10时,我们希望确保集合中只有9个项目,并且我们将新项目添加到其中。
现在你有一个可以从index,:articles-index查找的实体,并且可以从索引中查找最近的10篇文章(所有引用都被编入索引),而不会导致完整的数据库读取。
;; "indexed" set of articles.
(d/entity db :articles-index)
答案 2 :(得分:1)
我一直在研究这个问题,并认为我有一个更优雅的答案。
将您的属性声明为使用:db/index true
{:db/id #db/id[:db.part/db -1]
:db/ident :ocelot/number
:db/valueType :db.type/long
:db/cardinality :db.cardinality/one
:db/doc "An ocelot number"
:db/index true
:db.install/_attribute :db.part/db}
这可确保该属性包含在AVET索引中。
然后,以下内容可让您访问“前十名”,尽管使用的是低级datoms
来电。
(take-last 10 (d/datoms (db conn) :avet :ocelot/number))
显然,如果你需要进行任何进一步的过滤(“谁是这个俱乐部的前十名得分手??”)那么这种方法将无法运作,但那时你的要小得多手中的数据量,不需要担心索引。
我确实深入研究了Datalog提供的聚合功能,并且无法理解它们 - 我不确定max
将使用此索引而不是数据的完整扫描。类似地,(index-range ...)
函数几乎肯定会使用此索引,但需要您知道开始和/或结束值。