gpt4 book ai didi

clojure - 如何构造与DataScript中的引用向量完全匹配的查询?

转载 作者:行者123 更新时间:2023-12-04 04:29:42 25 4
gpt4 key购买 nike

设置考虑以下电影和类型转换的DataScript数据库,以及从learndatalogtoday.org中窃取的数据:只要project.clj包含[datascript "0.15.0"]作为依赖项,就可以在JVM/Clojure REPL或ClojureScript REPL中执行以下代码。

(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)

说明概括地说,该数据库中有两种实体-电影和 Actor (打算不使用文字的单词)-三种硅藻:
  • 电影实体::film/name(唯一字符串)
  • 电影实体::film/cast(多个引用)
  • Actor 实体::actor/name(唯一字符串)

  • 问题我想构造一个查询,该问题是:对于N> = 2,哪些电影具有这些 N Actor ,而仅这些 N Actor 是唯一的明星?

    例如,RoboCop由Nancy Allen,Peter Weller,Ronny Cox主演,但没有一部电影仅由Allen和Weller主演。因此,我希望以下查询产生空集:
    (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"]}

    但是,该查询存在缺陷,因为我不知道该如何表达任何比赛都应排除非艾伦或韦勒的 Actor -同样,我想找到只有艾伦和韦勒没有其他 Actor 合作的电影,因此我想调整上面的查询以产生空集。如何调整此查询以强制执行此要求?

    最佳答案

    因为DataScript没有取反(截至2016年5月),所以我认为使用“纯” Datalog中的一个静态查询是不可能的。

    我的方法是:

  • 以编程方式构建查询,以添加N个子句,该子句声明强制类型转换必须包含N个参与者
  • 添加一个谓词函数,在给定电影,数据库和 Actor ID集合的情况下,使用EAVT索引查找每个电影中是否有不在集合中的 Actor 。

  • 这是一个基本的实现
    (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?)))

    关于clojure - 如何构造与DataScript中的引用向量完全匹配的查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37200086/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com