Fork me on GitHub

One of the things that set Asami apart seems to be have it handles attributes with multiple values. Instead of making a distinction via the schema it allows setting array values which get represented as linked lists in the graphs. Are there any ways to manipulate these like, like add/remove a single element?


Yes. Asami takes the RDF approach. This is intentional


But it means that if your data is structured like an entity (which usually only has one value per attribute), then you either want to use transact to insert/update the data as an entity and not with datoms, or else you need to be careful


I also noticed that if you transact an array value, then try to transact a regular value for the same entity/attribute, it still returns the array when you query afterwards


I’m not sure what you mean here… Did you do something like:

(transact conn [{:db/ident "mary"
                 :name "Mary"
                 :children ["Aaron", "Betty"]}])
(transact conn [{:db/ident "mary"
                 :children "Charles"}])


I’m expecting that it’s something like that, since it would lead to the behavior that you state.


If you wanted to append to the array, then at this point I’m expecting you to rewrite the array. i.e.:

(transact conn [{:db/ident "mary"
                 :children' ["Aaron" "Betty" "Charles"]}])


But… I can see that adding to that attribute would more naturally append to the array. I could do that…


Yeah that's exactly what I did. Just trying some stuff out to get a better feel of how Asami deals with things. In this case I actually expected it would return "charles" as a single value...


But don't take that as a feature request, I'm just trying to test my mental model


I’ll take this back to the main room…


There’s a new set of behaviors….


if you assert a set as a value, then it stores that as a multi-arity value


if you have multiple values on an attribute, then it comes back as a set


so if you add:

{:db/ident "anna" :age 31}
and then transact:
{:db/ident "anna" :age 32}
Then when you get the “anna” entity, it will come back with:
{:age #{31 32}}


As already documented, if you wanted to replace it, you needed to transact:

{:db/ident "anna" :age' 32}


But the OTHER new thing, is that you can append to arrays now


So if you start with:

{:db/ident "anna" :age 31 :friends ["John" "Ringo" "Paul"]}
Then you can transact:
{:db/ident "anna" :friends+ "George"}
And when you get the “anna” entity again, you’ll retrieve:
{:age 31 :friends ["John" "Ringo" "Paul" "George"]}


It’s all in asami-1.1.0-SNAPSHOT. I’ll test it more heavily in the morning, and document it before I release it as 1.1.0


When you query with asami.core/q or when you use the asami.core/entity function?


The entity function makes a presumption that you didn’t try to modify the data, so it’s not expecting multiple uses of an attribute


The entity function is just looking for one value per attribute. If you have 2, then it will just return the first one that it finds. I have a ticket to instead return a set for attributes that have multiple values


From the thread above…


Asami features have mostly been driven by use cases. The rest of it has come about by me wanting to choose what I hoped were sensible defaults


Since it’s schemaless, I have not tried to duplicate Datomic exactly


I have been giving a bit of thought to what it means to add data that relates to an existing entity. Do I replace attributes? Do I append? How do I stay consistent with those cases where the attribute doesn’t exist? How do I minimize the work that’s done? After all, I can just remove all triples that pertain to an object, and then insert new ones. But that has performance costs in needing to query and then re-insert, and do I want to wear that overhead for every transaction?


This was what drove the introduction of annotated attributes


These force a lookup and modification of the existing structure, rather than just blindly inserting