0

I’ve got an account model that has interests, which is an array of strings (db.type=string and cardinality=many). For example:

{:id 42
 :name "Test"
 :interests ["cars" "games" "etc"]
 :age 50}

Then another list of interests come from the request. How can I query accounts what have ALL the specified interests?

For example, for ["cars" "games"] I'll get the account #42 since it includes the passed list. But for ["cars" "games" "books"] I won't because "books" is an extra one.

UPD

What I have is:

;; model
{:db/ident       :account/interests
 :db/valueType   :db.type/string
 :db/cardinality :db.cardinality/many
 :db/index       true}

;; a query
[:find ?id
 :id $ [?interest ...]
 :where
 [?a :account/interests ?interest]
 [?a :account/id        ?id]]

So how should I build a Datomic query?

Ivan Grishaev
  • 1,583
  • 10
  • 15
  • Possible duplicate of [Find entities whose ref-to-many attribute contains all elements of input](https://stackoverflow.com/questions/43784258/find-entities-whose-ref-to-many-attribute-contains-all-elements-of-input) – Valentin Waeselynck Dec 22 '18 at 00:01

2 Answers2

1

Try using entities in a query

(d/q '[:find ?e
       :in $ ?interests
       :where
       [?e :interests _]
       [(datomic.api/entity $ ?e) ?ent]
       [(:interests ?ent) ?ent_interests]
       [(subset? ?interests ?ent_interests)]]
     (d/db conn)
     #{"cars" "games"})
Niki Tonsky
  • 1,327
  • 11
  • 19
1
(time (d/q

   '[:find ?id
     :in $
     :where

     [?a :account/interests "foo"]
     [?a :account/interests "bar"]
     [?a :account/id ?id]]

   (d/db conn)))

"Elapsed time: 3.771973 msecs"

(time (d/q

   '[:find ?id
     :in $ ?iii
     :where

     [(datomic.api/entity $ ?a) ?e]
     [(:account/interests ?e) ?interests]
     [(clojure.set/superset? ?interests ?iii)]
     [?a :account/id ?id]]

   (d/db conn)
   #{"50 Cent" "Целоваться"}))

"Elapsed time: 169.767354 msecs"

The first one is better.

Ivan Grishaev
  • 1,583
  • 10
  • 15