2014-09-26 3 views
3

필터링을 수행하는 것을 Datomic 내가 효율적으로 같은 쿼리를 지원하는 방법 궁금하네요 does not support pagination : 그 :history/body 일치효율적인 Datomic 쿼리를 감안할 때 매겨진 세트

찾아 :history/body에 처음 30 개체를 타고 실체 일부 정규식.

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

관찰 : 여기

은 나 혼자 정규식 일치 할 거라고 방법

  1. 것과 내가 할 수 다음 (take ...)을,하지만 그건에 대해 일치로 하지 동일 처음 30 개의 개체.
  2. 나는 수동 re-find로 필터링 모든 기관, take 30를 얻을 수 있지만, 난 그냥 take 30에 그들 모두를 받고, 30M 기관이있는 경우 격렬하게 비효율적 인 것 같습니다 수 있습니다. 또한 30M 개체에서 20M을 가져 와서 re-find을 통해 필터링하고 싶다면 어떻게해야합니까?

Datomic 문서가 쿼리를 로컬로 실행하는 방법에 대해 이야기하지만, 나는 52,913 개체의 집합에 메모리 변환을하고 해봤 (부여, 그들은 완전히 touch 에드이야) 그리고 ~ 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 엔티티를 paginating 된 경우 :

(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