2014-09-26 17 views
3

鉴于过滤是Datomic does not support pagination我不知道如何有效地支持查询,如:高效Datomic查询来执行对分页套

在第一个30个实体上:history/body,找到实体的 :history/body一些比赛正则表达式。

这是我怎么会做单独的正则表达式匹配:

{:find [?e] 
:where [[?e :history/body ?body] 
     [(re-find #"foo.*bar$" ?body)]]} 

观察:

  1. 然后我可以从这些(take ...),但就是一样对匹配前30个实体。
  2. 我能得到所有实体,take 30然后用re-find手动筛选,但如果我有30M的实体,让所有的人都只是为了take 30似乎疯狂效率低下。另外:如果我想从我的30M实体中抽取20M并通过re-find进行过滤,该怎么办?

Datomic文档谈论了查询如何在本地执行,但我已经试过了一套52913个实体做内存变换(当然,他们是完全touch ED),它大约需要5秒。想象一下,在数百万甚至上千万中会有多糟糕。

回答

1

(只是集思广益,在这里)

首先,如果你曾经使用正则表达式,你可能要考虑一个全文索引:历史/身体,使你可以做:

[(fulltext $ :history/body "foo*bar") [[?e]]] 

(注意:您无法在现有实体架构上更改:db/fulltext true/false

排序是您必须在查询之外执行的操作。但根据您的数据,您可能会将查询约束为单个“页面”,然后将谓词应用于这些实体。

例如,如果我们只用一个自动递增:history/id,然后我们会事先知道,“第3页”是:history/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]]] 

也许是这样的分页:history实体:

(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))) 

但是,当然,问题是制约分页集通常是基于一个命令你不提前知道,所以这是不是非常有帮助。

+0

谢谢。当我有机会时,我会努力通过这个,看起来像一个好的开始。 – devth 2014-10-08 16:03:35