Not possible to pass attributes as argument for fulltext used inside or-join

Hi, query execution fails when I’m trying to execute the next datalog query:

(d/q "[
:find ?user 
:in $ [?userNameAttrs1 ...] [?userNameAttrs2 ...]  ?userNameValue1 ?userNameValue2
:where 
(or-join [?user ?userNameAttrs1 ?userNameAttrs2 ?userNameValue1 ?userNameValue2]
  [(fulltext $ ?userNameAttrs1 ?userNameValue1) [[?user _ _ _]]]
  [(fulltext $ ?userNameAttrs2 ?userNameValue2) [[?user _ _ _]]]
)
]"
(d/db conn), [:user/name.EN :user/name.ES] [:user/name.EN :user/name.ES]  "Bob*" "Tob*" )

Error is:

Execution error (ArrayIndexOutOfBoundsException) at (REPL:1).
null

The schema is the next:

(def user-schema [
                    {
                      :db/ident :user/kind
                      :db/valueType :db.type/string
                      :db/cardinality :db.cardinality/one
                   }
                   {
                       :db/ident :user/name.EN
                       :db/valueType :db.type/string
                       :db/cardinality :db.cardinality/one
                       :db/fulltext true
                   }
                   {
                       :db/ident :user/name.ES
                       :db/valueType :db.type/string
                       :db/cardinality :db.cardinality/one
                       :db/fulltext true
                   }

                   ])
(d/transact conn user-schema)

and transacted data:

(def user-data [
  {
    :user/kind "owner"
    :user/name.EN "Boby"
    :user/name.ES "Doby"
  }
  {
    :user/kind "owner"
    :user/name.EN "Doby"
    :user/name.ES "Boby"
  }
  {
    :user/kind "owner"
    :user/name.EN "Mobi"
    :user/name.ES "Tobi"
  }
])
(d/transact conn user-data)

What is interesting, if to remove or-join then all works:

(d/q "[
:find ?user 
:in $ [?userNameAttrs1 ...] [?userNameAttrs2 ...] ?userNameValue1 ?userNameValue2
:where 
[(fulltext $ ?userNameAttrs1 ?userNameValue1) [[?user _ _ _]]]
[(fulltext $ ?userNameAttrs2 ?userNameValue2) [[?user _ _ _]]]
]"
(d/db conn), [:user/name.EN :user/name.ES] [:user/name.EN :user/name.ES] "Bob*" "Tob*" )

Result:
#{}

Also you could ask me, why I’m passing attributes as variable instead of passing collection of keywords directly, unfortunately otherwise I’m getting error:

(d/q "[
:find ?user 
:in $ ?userNameValue1
:where 
[?user [:user/name.EN :user/name.ES] ?userNameValue1]
]"
(d/db conn), "Boby")

Execution error (Exceptions$IllegalArgumentExceptionInfo) at datomic.error/arg (error.clj:79).
:db.error/lookup-ref-attr-not-unique Attribute values not unique: :user/name.EN

Further is more interesting, I was wondering whether variables used to pass idents of attributes should be passed as arguments for or-joins, let’s consider the next case:

(d/q "[
:find ?user 
:in $ [?userNameAttrs1 ...] [?userNameAttrs2 ...] ?userNameValue1 ?userNameValue2
:where 
(or-join [?user ?userNameValue1 ?userNameValue2]
  [?user ?userNameAttrs1 ?userNameValue1]
  [?user ?userNameAttrs2 ?userNameValue1]
)
]"
(d/db conn), [:user/name.EN :user/name.ES] [:user/name.EN :user/name.ES] "Boby" "Toby" )

Result is returned, all works fine, but if or-join inputs contains variables which nest attribute idents then the same error is happen as for example with fulltext:

(d/q "[
:find ?user 
:in $ [?userNameAttrs1 ...] [?userNameAttrs2 ...] ?userNameValue1 ?userNameValue2
:where 
(or-join [?user ?userNameAttrs1 ?userNameAttrs2 ?userNameValue1 ?userNameValue2]
       [?user ?userNameAttrs1 ?userNameValue1]
       [?user ?userNameAttrs2 ?userNameValue1]
)
]"
(d/db conn), [:user/name.EN :user/name.ES] [:user/name.EN :user/name.ES] "Boby" "Toby" )
Execution error (ArrayIndexOutOfBoundsException) at (REPL:1).
null

So looks like variables which nest attribute idents should not be passed as arguments for or-joins but on other hand passing of variables to functions inside or-joins requires declaring of these variables as input arguments for or-joins

P.S. Easy solving of this issue might be allowing of specifying of attributes inside datomos directly without necessity to pass its as variables

[?user [:user/name.EN :user/name.ES] ?userNameValue1]

P.P.S. @marshall Not sure but might it be somehow related to Order of variables matters when attributes are passed as arguments there issue is related to variables used for passing attribute idents too?

1 Like