2016-05-13 5 views
8

सेटअप पर विचार करें फिल्मों और कलाकारों के निम्नलिखित DataScript डेटाबेस, learndatalogtoday.org से चोरी डेटा के साथ: निम्नलिखित कोड, एक JVM/Clojure REPL या एक ClojureScript आरईपीएल में क्रियान्वित किया जा सकता जब तक project.clj[datascript "0.15.0"] किसी निर्भरता के रूप में शामिल है के रूप में।डेटास्क्रिप्ट में रेफरी के एक वेक्टर से मेल खाने वाली क्वेरी कैसे बनाएं?

  • फिल्म इकाई:

    (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 करने का इरादा) और datoms के तीन प्रकार हैं: :film/name (एक अद्वितीय स्ट्रिंग)

  • फिल्म इकाई: :film/cast (कई refs)
  • अभिनेता इकाई: :actor/name (अद्वितीय स्ट्रिंग)

प्रश्न मैं एक प्रश्न जो पूछता है का निर्माण करना चाहते हैं: जो फिल्मों इन N अभिनेताओं, और इन N अभिनेताओं अकेले है, एन> = 2 के लिए, एकमात्र सितारों के रूप में दिखाई दिया?

ई.जी., रोबोकॉप ने नैन्सी एलन, पीटर वेलर, रोनी कॉक्स की भूमिका निभाई, लेकिन नहीं फिल्म पूरी तरह से इन दोनों में से दो, एलन और वेयर तारांकित हुई। इसलिए, मैं निम्न क्वेरी खाली सेट का उत्पादन की उम्मीद करेंगे:

(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- नहीं हैं शामिल नहीं होना चाहिए पता नहीं है दोबारा, मैं उन फिल्मों को ढूंढना चाहता हूं जहां केवल एलन और वेयर ने किसी अन्य अभिनेता के बिना सहयोग किया है, इसलिए मैं उपरोक्त क्वेरी को खाली सेट का उत्पादन करने के लिए अनुकूलित करना चाहता हूं। इस आवश्यकता को लागू करने के लिए मैं इस क्वेरी को कैसे समायोजित कर सकता हूं?

उत्तर

2

क्योंकि डेटास्क्रिप्ट में अस्वीकृति नहीं है (मई 2016 तक), मुझे विश्वास नहीं है कि 'शुद्ध' सूची में एक स्थिर क्वेरी के साथ यह संभव है।

जाना मेरे तरीका होगा:

  1. क्वेरी बनाने के प्रोग्राम के रूप में एन खंड बताती हैं कि कलाकारों एन अभिनेताओं शामिल होना चाहिए जोड़ने के लिए
  2. एक विधेय समारोह जो, एक फिल्म दी जोड़ें, डेटाबेस, और अभिनेता आईडी के सेट, ईएवीटी इंडेक्स का उपयोग यह पता लगाने के लिए करता है कि प्रत्येक मूवी में एक अभिनेता है जो सेट में नहीं है।

यहाँ एक बुनियादी कार्यान्वयन

(defn only-those-actors? [db movie actors] 
    (->> (datoms db :eavt movie :film/cast) seq 
    (every? (fn [[_ _ actor]] 
       (contains? actors actor))) 
    )) 

(defn find-movies-with-exact-cast [db actors-names] 
    (let [actors (set (d/q '[:find [?actor ...] :in $ [?name ...] ?only-those-actors :where 
          [?actor :actor/name ?name]] 
         db actors-names)) 
     query {:find '[[?movie ...]] 
       :in '[$ ?actors ?db] 
       :where 
       (concat 
       (for [actor actors] 
        ['?movie :film/cast actor]) 
       [['(only-those-actors? ?db ?movie ?actors)]])}] 
    (d/q query db actors db only-those-actors?))) 
+0

देरी के लिए खेद है (और आपको ढीला करने के लिए खेद है)! प्रश्न में * केवल-वे-अभिनेता? * * जैसे चेक डालने का कोई फायदा है? वर्स बस क्वेरी के बाहर सभी हिट और पोस्ट-प्रोसेसिंग प्राप्त कर रहा है, प्रति https://gist.github.com/fasiha/647a48420770536a4fa952a4b38f69d7#file-stackoverflow-clj-L97-L116? क्या यह कार्यान्वयन 'डेटाम' मार्ग पर नहीं जा रहा है? –

+0

आप कार्यान्वयन भी ठीक लग रहा है! आप अलग का चालाक उपयोग करते हैं। एक अनुकूलन के रूप में, हो सकता है कि आप केवल विशिष्ट कलाकारों की संख्या को गिनें, जो सॉर्टिंग से अधिक कुशल हैं। डेटाम का उपयोग करने के बारे में या नहीं: मैं प्रदर्शन के बारे में कोई दावा नहीं करूंगा, आपको बेंचमार्क चलाना चाहिए। –

+0

मुझे कोड में एक या दो अतिरिक्त चीजों को साफ़ करना था क्योंकि वर्तमान में यह है: https://gist.github.com/fasiha/647a48420770536a4fa952a4b38f69d7#file-stackoverflow-clj-L60-L85 (यदि आप अपडेट करना चाहते हैं जवाब) लेकिन यह काम करता है! धन्यवाद!! –

0

है आप एक ऐसी इकाई के :film/cast क्षेत्र के आधार पर फ़िल्टर datoms के लिए एक साथ विधेय मज़ा और d/entity उपयोग कर सकते हैं। यह दृष्टिकोण अधिक सरल दिखता है जब तक कि डेटास्क्रिप्ट अस्वीकृति का समर्थन नहीं करता है ( ऑपरेटर और इसी तरह)।Datascript here

[{:db/id 1 :name "Ivan" :age 10} 
{:db/id 2 :name "Ivan" :age 20} 
{:db/id 3 :name "Oleg" :age 10} 
{:db/id 4 :name "Oleg" :age 20}] 

... 

(let [pred (fn [db e a] 
      (= a (:age (d/entity db e))))] 
    (is (= (q/q '[:find ?e 
       :in $ ?pred 
       :where [?e :age ?a] 
         [(?pred $ ?e 10)]] 
       db pred) 
     #{[1] [3]}))))) 

आपके मामले में की कसौटी पर मामले में पंक्ति (= a (:age (d/entity db e)) पर

देखो, विधेय शरीर कुछ इस

(clojure.set/subset? actors (:film/cast (d/entity db e)) 

की तरह प्रदर्शन करने के लिए, d/entity दिखाई दे सकता है संबंध कॉल तेज है क्योंकि यह इंडेक्स द्वारा एक लुकअप है।

संबंधित मुद्दे

 संबंधित मुद्दे