Discussion:
Datomic 'unique identity' vs 'unique value'
Arun Mani
2017-11-02 00:59:50 UTC
Permalink
The Datomic documentation
(http://docs.datomic.com/identity.html#unique-identities) suggests keeping
database-wide unique identities like email ids as "unique identity"
attributes. There aren't any usecases mentioned in the same documentation
for "unique value" attributes except to point out the critical difference
that they throw an exception if a datom with that attribute and value
combination already exists in the latest version of the db.

My own experience suggests though, in cases where we create entities with
database-wide unique ids (say, user accounts with a unique username
attribute), "upsert" semantics do not work well while creating such user
account entities, and I will need a transaction function to create these
correctly. Otherwise we may have a potential race condition if two users
create accounts with identical usernames around the same time. The only way
out is to write a transaction function for creating new user accounts.

On the other hand, the exception mechanism of "unique value" attributes are
exactly what I want for this usecase. I try to add a new user, and if I get
an 'IllegalStateException' I know there is a duplicate account with the
same username. (I should, of course, still check the current db as a first
step so as not to bother the transactor with easily spotted duplicate
requests.) The price I pay for this is that at update time I lose 'upsert',
and so will need to translate the value of the username attribute to a
Datomic entity id to be
able to update that user account. (I personally think that the lookup refs
mean that this isn't too much of a price to pay.)

So am I correct in understanding that the choice between "unique identity"
and "unique value" in my case is a choice between
1) being able to work with domain values directly for update operations but
at the cost of a tx function for the initial creation operation, or
2) having to use a 'lookup ref' for update operations but without the cost
of writing a tx function for the initial creation.

If this is correct, the Datomic documentation should preferably explain
this, and if this is not correct, please correct my misunderstanding.

Thanks,
- Arun
--
You received this message because you are subscribed to the Google Groups "Datomic" group.
To unsubscribe from this group and stop receiving emails from it, send an email to datomic+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Daniel Compton
2017-11-02 02:37:36 UTC
Permalink
Hi Arun

I agree, the Datomic docs could do more here to explain the tradeoffs and
when you should choose one or the other. The rule of thumb is to use
identity for things that identify the user, and value for things that
cannot be duplicated in the system, but aren't used as identifiers. I think
a good example is the case of a product. It has an internal Stock Keeping
Unit (SKU) identity that the system/company works with, and it also has a
barcode. The barcode must be unique within the system, but isn't actually
the identity for the product.

Another example is a user record that has an email and a username. The
username is the identity in the system, whereas you want to add a
constraint that the email must be unique.

This breaks down a little bit if you think about it too much, because if
some value must be unique, it could also be used as an identifier, but I
find it a helpful way to keep them straight in my mind.
The Datomic documentation (
http://docs.datomic.com/identity.html#unique-identities) suggests keeping
database-wide unique identities like email ids as "unique identity"
attributes. There aren't any usecases mentioned in the same documentation
for "unique value" attributes except to point out the critical difference
that they throw an exception if a datom with that attribute and value
combination already exists in the latest version of the db.
My own experience suggests though, in cases where we create entities with
database-wide unique ids (say, user accounts with a unique username
attribute), "upsert" semantics do not work well while creating such user
account entities, and I will need a transaction function to create these
correctly. Otherwise we may have a potential race condition if two users
create accounts with identical usernames around the same time. The only way
out is to write a transaction function for creating new user accounts.
On the other hand, the exception mechanism of "unique value" attributes
are exactly what I want for this usecase. I try to add a new user, and if I
get an 'IllegalStateException' I know there is a duplicate account with the
same username. (I should, of course, still check the current db as a first
step so as not to bother the transactor with easily spotted duplicate
requests.) The price I pay for this is that at update time I lose 'upsert',
and so will need to translate the value of the username attribute to a
Datomic entity id to be
able to update that user account. (I personally think that the lookup refs
mean that this isn't too much of a price to pay.)
So am I correct in understanding that the choice between "unique identity"
and "unique value" in my case is a choice between
1) being able to work with domain values directly for update operations
but at the cost of a tx function for the initial creation operation, or
2) having to use a 'lookup ref' for update operations but without the cost
of writing a tx function for the initial creation.
If this is correct, the Datomic documentation should preferably explain
this, and if this is not correct, please correct my misunderstanding.
Thanks,
- Arun
--
You received this message because you are subscribed to the Google Groups "Datomic" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Datomic" group.
To unsubscribe from this group and stop receiving emails from it, send an email to datomic+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Alan Thompson
2017-11-02 05:42:25 UTC
Permalink
This passage shows the difference:

​​
Unique values have the same semantics as unique identities, with one
critical difference: Attempts to assert a new tempid with a unique value
already in the database will cause an IllegalStateException.


The only
​ difference is that *:db.unique/value*​ cannot be used for upsert
functionality, while *:db.unique/identity* can be used for upsert.
A
​lan​

On Wed, Nov 1, 2017 at 7:37 PM, Daniel Compton <
Post by Daniel Compton
Hi Arun
I agree, the Datomic docs could do more here to explain the tradeoffs and
when you should choose one or the other. The rule of thumb is to use
identity for things that identify the user, and value for things that
cannot be duplicated in the system, but aren't used as identifiers. I think
a good example is the case of a product. It has an internal Stock Keeping
Unit (SKU) identity that the system/company works with, and it also has a
barcode. The barcode must be unique within the system, but isn't actually
the identity for the product.
Another example is a user record that has an email and a username. The
username is the identity in the system, whereas you want to add a
constraint that the email must be unique.
This breaks down a little bit if you think about it too much, because if
some value must be unique, it could also be used as an identifier, but I
find it a helpful way to keep them straight in my mind.
The Datomic documentation (http://docs.datomic.com/identity.html#unique-
identities) suggests keeping database-wide unique identities like email
ids as "unique identity" attributes. There aren't any usecases mentioned in
the same documentation for "unique value" attributes except to point out
the critical difference that they throw an exception if a datom with that
attribute and value combination already exists in the latest version of the
db.
My own experience suggests though, in cases where we create entities with
database-wide unique ids (say, user accounts with a unique username
attribute), "upsert" semantics do not work well while creating such user
account entities, and I will need a transaction function to create these
correctly. Otherwise we may have a potential race condition if two users
create accounts with identical usernames around the same time. The only way
out is to write a transaction function for creating new user accounts.
On the other hand, the exception mechanism of "unique value" attributes
are exactly what I want for this usecase. I try to add a new user, and if I
get an 'IllegalStateException' I know there is a duplicate account with the
same username. (I should, of course, still check the current db as a first
step so as not to bother the transactor with easily spotted duplicate
requests.) The price I pay for this is that at update time I lose 'upsert',
and so will need to translate the value of the username attribute to a
Datomic entity id to be
able to update that user account. (I personally think that the lookup
refs mean that this isn't too much of a price to pay.)
So am I correct in understanding that the choice between "unique
identity" and "unique value" in my case is a choice between
1) being able to work with domain values directly for update operations
but at the cost of a tx function for the initial creation operation, or
2) having to use a 'lookup ref' for update operations but without the
cost of writing a tx function for the initial creation.
If this is correct, the Datomic documentation should preferably explain
this, and if this is not correct, please correct my misunderstanding.
Thanks,
- Arun
--
You received this message because you are subscribed to the Google Groups
"Datomic" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Datomic" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Datomic" group.
To unsubscribe from this group and stop receiving emails from it, send an email to datomic+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Dustin Getz
2017-11-02 12:34:18 UTC
Permalink
I believe ::identity simply turns on upsert, that's the only difference (As
Alan said)
--
You received this message because you are subscribed to the Google Groups "Datomic" group.
To unsubscribe from this group and stop receiving emails from it, send an email to datomic+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...