鉴于 Datomic does not support pagination我想知道如何有效地支持查询,例如:
Take the first 30 entities on
:history/body
, find entities whose:history/body
matches some regex.
这是我单独进行正则表达式匹配的方法:
{:find [?e]
:where [[?e :history/body ?body]
[(re-find #"foo.*bar$" ?body)]]}
观察结果:
- 然后我可以从这些实体中
(获取...)
,但这与匹配前 30 个实体不相同。 - 我可以获取所有个实体,
获取 30
,然后使用重新查找
手动过滤,但如果我有 30M 个实体,则获取所有他们仅仅拿 30
似乎效率极低。另外:如果我想从 30M 实体中取出 20M 并通过重新查找
过滤它们,该怎么办?
Datomic 文档讨论了如何在本地执行查询,但我尝试对一组 52913 个实体进行内存中转换(当然,它们是完全touch
ed),并且需要〜 5秒。想象一下,如果是数百万或数十百万的话,情况会有多糟糕。
最佳答案
(这里只是集思广益)
首先,如果您曾经使用过正则表达式,您可能需要考虑在 :history/body 上建立全文索引,以便您可以执行以下操作:
[(fulltext $ :history/body "foo*bar") [[?e]]]
(注意:您无法更改现有实体架构上的 :db/fulltext true/false
)
排序是您必须在查询之外执行的操作。但根据您的数据,您也许能够将查询限制在单个“页面”,然后将谓词仅应用于这些实体。
例如,如果我们仅通过自动递增的 :history/id
对 :history
实体进行分页,那么我们会事先知道“Page 3”是:历史记录/id
61 到 90。
[:find ?e
:in $ ?min-id ?max-id
:where
[?e :history/id ?id]
(<= ?min-id ?id ?max-id)
(fulltext $ :history/body "foo*bar") [[?e]]]
也许是这样的:
(defn get-filtered-history-page [page-n match]
(let [per-page 30
min-id (inc (* (dec page-n) per-page))
max-id (+ min-id per-page)]
(d/q '[:find ?e
:in $ ?min-id ?max-id ?match
:where
[?e :history/id ?id]
[(<= ?min-id ?id ?max-id)]
[(fulltext $ :history/body ?match) [[?e]]]]
(get-db) min-id max-id match)))
但是,当然,问题是约束分页集通常基于您事先不知道的顺序,因此这不是很有帮助。
关于clojure - 高效的 Datomic 查询对分页集执行过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26064582/