設置考慮膜和流延的下面DataScript數據庫,與來自learndatalogtoday.org竊取的數據:以下代碼可以在JVM/Clojure的REPL或ClojureScript REPL只要project.clj
包含[datascript "0.15.0"]
作爲依賴執行。如何構建一個完全匹配DataScript中的引用向量的查詢?
(ns user
(:require [datascript.core :as d]))
(def data
[["First Blood" ["Sylvester Stallone" "Brian Dennehy" "Richard Crenna"]]
["Terminator 2: Judgment Day" ["Linda Hamilton" "Arnold Schwarzenegger" "Edward Furlong" "Robert Patrick"]]
["The Terminator" ["Arnold Schwarzenegger" "Linda Hamilton" "Michael Biehn"]]
["Rambo III" ["Richard Crenna" "Sylvester Stallone" "Marc de Jonge"]]
["Predator 2" ["Gary Busey" "Danny Glover" "Ruben Blades"]]
["Lethal Weapon" ["Gary Busey" "Mel Gibson" "Danny Glover"]]
["Lethal Weapon 2" ["Mel Gibson" "Joe Pesci" "Danny Glover"]]
["Lethal Weapon 3" ["Joe Pesci" "Danny Glover" "Mel Gibson"]]
["Alien" ["Tom Skerritt" "Veronica Cartwright" "Sigourney Weaver"]]
["Aliens" ["Carrie Henn" "Sigourney Weaver" "Michael Biehn"]]
["Die Hard" ["Alan Rickman" "Bruce Willis" "Alexander Godunov"]]
["Rambo: First Blood Part II" ["Richard Crenna" "Sylvester Stallone" "Charles Napier"]]
["Commando" ["Arnold Schwarzenegger" "Alyssa Milano" "Rae Dawn Chong"]]
["Mad Max 2" ["Bruce Spence" "Mel Gibson" "Michael Preston"]]
["Mad Max" ["Joanne Samuel" "Steve Bisley" "Mel Gibson"]]
["RoboCop" ["Nancy Allen" "Peter Weller" "Ronny Cox"]]
["Braveheart" ["Sophie Marceau" "Mel Gibson"]]
["Mad Max Beyond Thunderdome" ["Mel Gibson" "Tina Turner"]]
["Predator" ["Carl Weathers" "Elpidia Carrillo" "Arnold Schwarzenegger"]]
["Terminator 3: Rise of the Machines" ["Nick Stahl" "Arnold Schwarzenegger" "Claire Danes"]]])
(def conn (d/create-conn {:film/cast {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many}
:film/name {:db/unique :db.unique/identity
:db/cardinality :db.cardinality/one}
:actor/name {:db/unique :db.unique/identity
:db/cardinality :db.cardinality/one}}))
(def all-datoms (mapcat (fn [[film actors]]
(into [{:film/name film}]
(map #(hash-map :actor/name %) actors)))
data))
(def all-relations (mapv (fn [[film actors]]
{:db/id [:film/name film]
:film/cast (mapv #(vector :actor/name %) actors)}) data))
(d/transact! conn all-datoms)
(d/transact! conn all-relations)
描述概括地說,有兩種類型的實體在該數據庫中的膜和演員(字旨在被ungendered) - 和3種datoms的:
- 膜實體:
:film/name
(唯一的字符串) - 膜實體:
:film/cast
(多參考文獻) - 演員實體:
:actor/name
(唯一的字符串)
問題我想構造一個問一個查詢:該薄膜具有這些N
演員,這些N
演員單獨,出現了作爲唯一的明星,對於N> = 2?
例如,RoboCop出演的Nancy Allen,Peter Weller,Ronny Cox,但是沒有這部電影僅僅是艾倫和韋勒的前兩部。因此,我希望下面的查詢產生空集:
(d/q '[:find ?film-name
:where
[?film :film/name ?film-name]
[?film :film/cast ?actor-1]
[?film :film/cast ?actor-2]
[?actor-1 :actor/name "Nancy Allen"]
[?actor-2 :actor/name "Peter Weller"]]
@conn)
; => #{["RoboCop"]}
但是,查詢是有缺陷的,因爲我不知道該如何表達,任何比賽應該排除誰不阿倫或Weller-任何演員再次,我想找到只有艾倫和韋勒沒有任何其他演員合作的電影,所以我想調整上述查詢來產生空集。我如何調整此查詢以執行此要求?
對不起,延遲了(抱歉讓你煩惱)!在查詢中加入像「只有那些演員」這樣的檢查有什麼好處嗎?與通過https://gist.github.com/fasiha/647a48420770536a4fa952a4b38f69d7#file-stackoverflow-clj-L97-L116獲取查詢外的所有匹配和後處理相比,這個實現是否會因爲不去'datoms'路由而受到影響? –
你的實現看起來也不錯!你巧妙地使用獨特的。作爲一種優化,也許你可以只計算不同角色的數量,這比排序更有效。關於是否使用datoms:我不會對性能做任何聲明,你應該運行基準測試。 –
我不得不在代碼中清理一個或兩個額外的東西,因爲它是目前:https://gist.github.com/fasiha/647a48420770536a4fa952a4b38f69d7#file-stackoverflow-clj-L60-L85(如果你想更新答案),但它的作品!謝謝!! –