2015-05-20 21 views
5

Obecnie pracuję nad migracją mojej aplikacji clojure (z korma) do Datomic framework i byłem w pętli podczas tłumaczenia zapytań. Rozumiem, że zapytania nie są całkowicie elastyczne (w porównaniu do Korma), na przykład chciałbym ocenić klauzule warunkowe wokół różnych zmiennych.Datomic - praca z klauzulą ​​OR

Zważywszy zapytania korma,

(select users 
    (where (or (and {:first_name [= "user"]} 
        {:last_name [= "sample"]}) 
       {:email [= "[email protected]"]}))) 

ten można przekształcić w Datomic, z czymś takim?

[:find ?e 
    :where (or (and [?u :user/first-name "user"] 
        [?u :user/last-name "sample"]) 
      [?u :user/email "[email protected]"]) 

ale nie jest to zalecane sposób wysyłania zapytań (według Datomic Dokumenty), ponieważ wszystkie klauzule stosowane w sposób albo klauzuli musi wykorzystać ten sam zestaw zmiennych. Jak ustawić klauzulę OR wokół różnych zestawów zmiennych?

Odpowiedz

5

Twoje zapytanie powinno działać. Wszystkie swoje klauzul zrobić używać tej samej zmiennej: ?u

(d/q '[:find ?u 
     :where (or (and [?u :user/first-name "user"] 
         [?u :user/last-name "sample"]) 
        [?u :user/email "[email protected]"])] 
    [[1 :user/first-name "user"] 
    [1 :user/last-name "sample"] 
    [2 :user/email "[email protected]"] 
    [3 :user/first-name "user"] 
    [3 :user/last-name "not sample"]]) 

=> #{[1] [2]} 

Jeśli trzeba je stosować różne zmienne, można użyć or-join jawnie je wymienić:

(d/q '[:find ?u 
     :in $ ?first-name ?last-name ?email 
     :where (or-join [?u ?first-name ?last-name ?email] 
       (and [?u :user/first-name ?first-name] 
        [?u :user/last-name ?last-name]) 
       [?u :user/email ?email])] 
    [[1 :user/first-name "user"] 
     [1 :user/last-name "sample"] 
     [2 :user/email "[email protected]"] 
     [3 :user/first-name "user"] 
     [3 :user/last-name "not sample"]] 
    "user" 
    "sample" 
    "[email protected]") 

=> #{[1] [2]} 
+0

'(d/q„[(niesprawdzone!): Znaleźć u :? W $ pierwszej nazwa przeszło nazwa? e-mail : gdzie (lub (i [? u: nazwa użytkownika/imię? pierwsza nazwa] [? u: nazwa użytkownika/nazwisko? nazwisko]) [? u: użytkownik/e-mail? ])] ' nie działałoby w takim przypadku, ponieważ zmienne są różne ent –

+0

Zaktualizowałem odpowiedź dla tego scenariusza. –

0

ta jest bardzo podobna do to pytanie:

SQL LIKE operator in datomic

trzeba sprawdzić zapytanie regulamin.

http://docs.datomic.com/query.html

Zapytanie wyglądałby coś takiego

(let [rules '[[(find-user ?user ?fname ?lname ?email) 
       [?user :user/first-name ?fname] 
       [?user :user/last-name ?lname]] 
       [(find-user ?user ?fname ?lname ?email) 
       [?user :user/email ?email]]]] 

    (:find ?user 
     :in $ % ?fname ?lname ?email 
     :where 
     (find-user ?user ?fname ?lname ?email) 
     conn rules "user" "sample" "[email protected]"))