Fork me on GitHub
#xtdb
<
2023-05-18
>
hifumi12307:05:13

What is considered best practice for updating an entity’s attribute? I have a situation where I am storing a “map” and I want to “update” one of its keys. Should I be using a transaction function for this? Or should I make a function where I query for the target entity’s ID then call xt/entity to grab the full entity and ::xt/put an updated copy of it?

refset13:05:22

Hey @U0479UCF48H transaction functions provide you a clear path to perform other kinds of validations and logic over time but they are more involved to implement and understand initially, and also introduce a performance tax - however I would normally still recommend using first at least so you know how they work in practice. The alternative approach demands also using ::xt/match operations (alongside ::xt/put) and to implement backoff & retry logic in your application - which is arguably more complicated to get right in the long-run, however might be the best way to eek out maximum performance assuming contention on changes to individual entities isn't high. This is because the transaction function approach typically involves doing much more I/O and serde work serially in the critical (blocking, single-threaded) write path, whereas put+`match` only requires dealing with a few hashes rather than the data itself.

👍 2
seancorfield15:05:35

@U899JBRPF in 2.0 you can do a sql update on a single column - what does that map to, under the hood? A tx function?

refset15:05:49

> what does that map to, under the hood? A tx function? Something roughly equivalent to a tx function, yes. There is no document-level machinery in 2.x that works based on "content hashes" like ::xt/match in 1.x

👀 2
seancorfield16:05:16

Right, because of the columnar architecture. Cool. Thanks -- didn't mean to hijack the thread... I was just curious.

👍 4
🙂 2
Aditya Sheth20:05:51

Hey folks! Had a quick question. I'm trying to get a query to return true or false based on if the count of queried entities is greater than 0. Something of this form:

{:query {:find [(if (> (count ?e) 0) true false)], :keys [value] :where [[?e :xt/id] .......]]}}
When the count is indeed greater than 0, the right value is returned (`value: true`). However when it is 0, I'm getting back an empty result / empty list instead of the other value. It seems like in that case, the result returned from count is an empty result as well instead of 0. How can I update this query to get back value: false? Why doesn't count return 0? Thanks!

refset10:05:50

Hey @U057FKW64DQ ! 🙂 So the short answer is that an empty relation (where one or more logic vars cannot be bound to any value) never gets included in the result set and effectively short-circuits any other downstream logic, so this behaviour is not unexpected...although I recognise it's not terribly intuitive!

refset11:05:10

> How can I update this query to get back value: false? one option is to wrap this query in an outer query, something like (haven't tested)

{:find [b]
 :where [[(q {:find [(if (> (count ?e) 0) true false)], :keys [value] :where [[?e :xt/id] .......]]}) res]
         (or (and [(empty? res)]
                  [(identity false) b])
             [(identity res) [b]])]}

Aditya Sheth17:05:52

Great, thanks for the help!