Search code examples
clojuredatomicdatalogdatascript

Why logical "and" predicates do not work?


Tested on datascript 1.3.0

datoms:

[{:db/id -1 :name "Smith" :firstname "Oliver" :age 20}
 {:db/id -2 :name "Jones" :firstname "Oliver" :age 20}
 {:db/id -3 :name "Smith" :firstname "Amelia" :age 16}
 {:db/id -4 :name "Jones" :firstname "Amelia" :age 16}]

tried to query with logical and predicates below who are named Smith and aged older than 18 years, why did it return the unfiltered whole set?

'[:find ?firstname ?name
  :where
  [?p :name ?name]
  [?p :firstname ?firstname]
  [?p :age ?age]
  [(and (= ?name "Smith") (> ?age 18))]]

;;; wrong result: #{[Oliver Smith] [Oliver Jones] [Amelia Smith] [Amelia Jones]}

then changed to query with discrete predicates and got the satisfied result as expected.

'[:find ?firstname ?name
  :where
  [?p :name ?name]
  [?p :firstname ?firstname]
  [?p :age ?age]
  [(= ?name "Smith")]
  [(> ?age 18)]]

;;; correct result: #{[Oliver Smith]}

Do datomic and datascript or datalog in general only support data patterns scattered to discrete clauses? Are conventional logical operations and etc. incompatible here?


Solution

  • According to the manual you cannot use an and-clause just like that. The only way you can use an and-clause is when it is inside an or-clause:

    Inside the or clause, you may use an and clause to specify conjunction. This clause is not available outside of an or clause, since conjunction is the default in other clauses.