2014-09-26 62 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