# Exact unordered match of multi-valued string field

**URL:** https://forum.datomic.com/t/exact-unordered-match-of-multi-valued-string-field/365
**Category:** General
**Created:** [March 12, 2018, 3:31pm UTC](https://forum.datomic.com/t/exact-unordered-match-of-multi-valued-string-field/365 "2018-03-12T15:31:45Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![tar](https://avatars.discourse-cdn.com/v4/letter/t/f04885/32.png) [@tar](https://forum.datomic.com/u/tar)
#### Post date: [March 12, 2018, 3:31pm UTC](https://forum.datomic.com/t/exact-unordered-match-of-multi-valued-string-field/365/1 "2018-03-12T15:31:45Z")

</div>

Given documents:

```
{:myid 100
 :v [1 2 3 4]}
{:myid 200
 :v [3 4 2 1]}
{:myid 300
 :v [1 2]}
{:myid 400
 :v [1 2 3 4 5 6]}

```

How would I query for the `myid` values from any documents that have an exact match for a certain value of `v`, with elements in any order?

For example, let’s say I want to find `myid` from all documents where `v` is any permutation of `[1 2 3 4]`. i.e. what query can I write that would return `[100 200]`? Actually, I’d want the entities, not the value of `myid`, but it’s easier to explain this way.

At the moment if I had to do this, I’d reach for something like:

```
'[:find [?myid ...]
  :in $ [?vMatch ...]
  :where
  [?e :myid ?myid]
  [?e :v ?vMatch]
  [(count :v) (count ?vMatch)]]
```

---

<div class="post-metadata">

### Author: ![dustingetz](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.datomic.com/dustingetz/32/56_2.png) [@dustingetz](https://forum.datomic.com/u/dustingetz)
#### Post date: [March 12, 2018, 8:56pm UTC](https://forum.datomic.com/t/exact-unordered-match-of-multi-valued-string-field/365/2 "2018-03-12T20:56:46Z")

</div>

The issue is you need set equality on the actual set

```auto
(d/q '[:in $ ?needle
       :find (pull ?e [:community/name :community/category])
       :where
       [?e :community/category]
       [(datomic.api/entity $ ?e) ?fat]
       [(get ?fat :community/category) ?cs]
       [(= ?cs ?needle)]]
     $ #{"events" "news"})
=>
[[#:community{:name "belltown", :category ["events" "news"]}]
 [#:community{:name "Greenwood Blog", :category ["events" "news"]}]]

```

You can also define your own peer functions (if peer):

```auto
(defn f [$ e needle]
  (let [en (->> e (d/entity $) :community/category)]
    #_(println needle en)
    (= needle en)))

(->> (d/q '[:in $ ?needle
            :find (pull ?e [:community/name :community/category])
            :where
            [?e :community/category]
            [(user/f $ ?e ?needle)]]
          $ #{"events" "news"}))
=> #'user/f
=>
[[#:community{:name "belltown", :category ["events" "news"]}]
 [#:community{:name "Greenwood Blog", :category ["events" "news"]}]]

```

---

<div class="post-metadata">

### Author: ![dustingetz](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.datomic.com/dustingetz/32/56_2.png) [@dustingetz](https://forum.datomic.com/u/dustingetz)
#### Post date: [March 12, 2018, 10:44pm UTC](https://forum.datomic.com/t/exact-unordered-match-of-multi-valued-string-field/365/3 "2018-03-12T22:44:19Z")

</div>

Taking it home with a peer function for set matching, someone pls yell out a better name

```auto
(defn matches [$ e a v] (-> (datomic.api/entity $ e) (get a) (= v)))

(d/q '[:in $ ?needle
       :find (pull ?e [:community/name :community/category])
       :where
       [?e :community/category] 
       [(user/matches $ ?e :community/category ?needle)]] ; basically mongo.findOne
     $ #{"events" "news"})
=> #'user/matches
=>
[[#:community{:name "belltown", :category ["events" "news"]}]
 [#:community{:name "Greenwood Blog", :category ["events" "news"]}]]

```
