This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-31
Channels
- # announcements (3)
- # aws-lambda (1)
- # babashka (122)
- # beginners (241)
- # calva (28)
- # cider (7)
- # clara (7)
- # clj-kondo (43)
- # clojars (5)
- # clojure (326)
- # clojure-europe (60)
- # clojure-italy (2)
- # clojure-nl (4)
- # clojure-spec (21)
- # clojure-uk (4)
- # clojurescript (162)
- # cursive (30)
- # datomic (3)
- # editors (5)
- # emacs (4)
- # figwheel-main (1)
- # fulcro (24)
- # gratitude (3)
- # helix (7)
- # honeysql (20)
- # improve-getting-started (1)
- # introduce-yourself (11)
- # jobs (3)
- # joker (2)
- # kaocha (15)
- # lsp (21)
- # lumo (2)
- # meander (3)
- # off-topic (34)
- # re-frame (6)
- # reagent (1)
- # releases (4)
- # rum (2)
- # shadow-cljs (37)
- # spacemacs (16)
- # tools-deps (16)
- # vim (23)
- # xtdb (32)
It does, as of the recent 1.18.0 release: https://opencrux.com/reference/lucene.html#_checkpointing_lucene
Hi guys, I'm a bit stuck on a query that matches documents that for a given prop either have no value (ie the prop isn't in the doc) OR have a given value (= arg). I think made it work using the inverse logical statement like this:
... where-clause...
(conj '(not-join
[e ?user-id]
[e :list/user ?x]
[(not= ?x ?user-id)]))
For my better understanding of datalog: is there a "positive" way of expressing this using (or)
or (or-join)
?
edit
This appears to work:
(conj '(or-join
[e ?user-id]
[e :list/user ?user-id]
(not-join [e ?user-id] [e :list/user])))
Are these approaches correct?Hi @U052A8RUT your (edit) solution looks sensible enough to me, so if it works okay then you can probably move on already. However, we have a fairly similar looking solution for a similar sounding problem that might inspire a slightly simpler approach: https://github.com/juxt/crux/blob/64e6f1f15ef2e389c42b8f17533c000bed9d33d7/crux-test/test/crux/query_test.clj#L1776-L1779
in your solution where you have (not-join [e ?user-id] [e :list/user])
- without knowing how else ?user-id
is used/bound, I'm not certain it will return what you want. Are you getting nil
out of it? (Is it in the :find
?)
i'm not sure i'm following entirely. To clarify: I want to retrieve docs where this attribute doesn't exist, as well as the docs where it does exist AND is equal to a param value.
Ha, no it is not in the :find
The entire query is:
{:find '[e],
:where '[[e :list/id ?id]
(or-join [e ?user-id]
[e :list/user ?user-id]
(not-join [e ?user-id]
[e :list/user]))
[e :list/scope ?scope-id]],
:args [{?user-id 1,
?scope-id "case-1"}]}
This should work for you, I think:
(crux.api/q
{:find '[e],
:in '[?user-id ?scope-id]
:where '[[e :list/id] ;; no need to capture ?id in the triple clause if you're not using it
(or-join [e ?user-id]
[e :list/user ?user-id]
(and (not [e :list/user])
[(any? ?userid)]) ;; this is a noop predicate to keep the variables in the or-join legs balanced
[e :list/scope ?scope-id]]}
1
"case-1")
As an aside, assuming you're not stuck on an old Crux version for some reason, it's best to use :in
instead of :args
After upgrading to the latest Crux version, with-redefs do no longer work as expected. I typically use it in some tests to test my logic around getting different results from crux.
(ns crux-with-redefs
(:require [crux.api :as crux]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; with-redefs example
(def mem-node (crux/start-node {}))
(with-redefs [crux/submit-tx (fn [_ _] :this-should-fail)]
(crux/submit-tx
mem-node
[[:crux.tx/put {:crux.db/id 1
:person/name "Axon"}]]))
;; with - "20.12-1.13.0-beta"
;; => :this-should-fail
;; with - "1.18.1"
;; => #:crux.tx{:tx-id 0, :tx-time #inst "2021-08-31T14:34:03.184-00:00"}
(.close mem-node)
Is there an intentional change in Crux resulting in this?short answer: no π I get a distinct feeling I'm about to learn something about the innards of Clojure, though :thinking_face:
alright - in that time crux/submit-tx
has gone from being implemented via extend-protocol
to being implemented directly on a defrecord
- I wonder if there's anything about defrecord
s that mean their implementations bypass with-redefs
in any way (some form of inlining, maybe?)
looks that way:
(defprotocol P
(foo [_ a]))
(defrecord R []
P
(foo [_ a]
a))
(with-redefs [foo (constantly 10)]
(foo (->R) 42))
;; => 42
whereas:
(defprotocol P
(foo [_ a]))
(defrecord R [])
(extend-protocol P
R
(foo [_ a]
a))
(with-redefs [foo (constantly 10)]
(foo (->R) 42))
;; => 10
to workaround, if you're looking to simulate crux/submit-tx
throwing an error, you could try redef'ing one of the callees of that function instead - crux.api/conform-tx-ops
might be a good shout
ok, thanks for the info and the workaround. Any chance the Crux implementation will change or will this be a trade-off of the internal implementation you have chosen?
it's unlikely to change, but obviously can't guarantee it - the fact that submit-tx
calls conform-tx-ops
isn't part of the public API π
oh, I mean the change of going from extend-protocol
to defrecord
. That might have given you benefits that you do not want to revert for the sake of supporting with-redefs
oh, I see. yes, that one's similarly unlikely to be reverted - previously we were attaching the functionality to a Java class, whereas now we're using a Clojure record
you could also consider supplying your own implementation of PCruxNode
to that function, with reify
, say?
right. Now that I know it is not a bug and will stay, I'll take a look at my workaround options. Maybe it could be worth documenting in some test related part, the current behaviour was a bit surprising π Thanks for your support and looking into it, I also learned something about the Clojure internals π
if the protocol has extend via metadata set, then you could just change submit-tx to throw using with-meta