[Convex Ents] Asymmetrical self-directed 1:many edges
Is that possible with Convex Ents? doesnt see it in the docs. Point is that I want a reply functionality. Which means that there is one message that replies to another (asymmetrical) but you can only reply to one message. But one message can be replied to by many messages.
21 Replies
The docs say
Every edge has two "ends", each being an Ent. Those Ents can be stored in the same or in 2 different tables.So it sounds like "self-directed" edges are possible. However, there is a slight problem: you probably don't want to require every message to be a reply to some other message (that would require infinite messages or a cycle of replies). You want an optional 1:many edge, which is not possible
Making the singular end of the 1:many edge optional is not supported for now.https://github.com/xixixao/convex-ents/issues/5 To work around this, you could use foreign references directly, so each message has a
replyTo: v.optional(v.id("messages"))
GitHub
1:many edges require single cardinality end to be required Β· Issue ...
This will require more configuration, especially for cascading deletes. We'll hold off on adding this until we get people asking for it.
Thank you so much. I will try the workaround with putting the id directly into the field
I think the hard thing about putting the ID directly in the field is that to do joins, I don't think you can use Ents.
My understanding is that you could use vanilla Convex to do the join - but then you'd include the table to Pick and you'd always use vanilla Convex for that table.
Maybe there is a way to keep the table defined as an Ent, but still use vanilla Convex or convex-helpers' relationships, but I haven't tried it personally
Hmmm, I think about it and share my research
I would think you could use ents, couldn't you just do this within the loop of results via map? I think i'm unaware if any benefit exists using convex helpers. π
I went with ents so early on i never had any complex relationships with vanilla
Hi, if I try to set up the field like this:
I get this error:
I get this error:
field("replyTo", v.optional(v.id("messages")))
it happens π
So seems to work:
schema:
query:
im actually working on our chat thing rn, i use v.union(v.id('messages'), v.null())
what is the benefit of
v.union(v.id("messages"), v.null())
over v.optional(v.id("messages")
my understanding is if you were loading stuff from the ui, null is helpful to let you know if the data loaded empty, with undefined, it hasn't loaded yet. so its not as confusing
ok, hmmm, yeah
apparently the more code i write the more im letting nextjs do lots of small queries.
Hoigim Dang
YouTube
Null References The Billion Dollar Mistake
lecturerοΌTony Hoare
conferenceοΌQCon London 2009
topicοΌnull reference in programming language design
yeah null with c is a totally different game. our dx protects us from π₯
Thanks for sharing the approach to query directly in the replyTo property:
Do you prefer this approach over creating a asymmetrical self-directed many:many relationship between messages?
https://labs.convex.dev/convex-ents/schema#asymmetrical-self-directed-manymany-edges
Ent Schema - Convex Ents
Relations, default values, unique fields and more for Convex
The thing is that I don't want many to many relations. I want that you can only reply to one message. many to many would mean that one message can reply to multiple messages
With my method you can only insert one message to reply to
Yeah, your business logic wouldnβt include many to many. I believe Michal wrote to do many to many as a workaround to the limitation of not being able to do an optional one to many.
Maybe I need to re-read this whole post. I think when you first made this post, you were looking for an optional one:many, and then the post title got edited to the asymmetric self referencing. So maybe what Iβm saying is no longer relevant .
It still needs to be optional. Not every message replies to another
You can write messages that don't reply
Right, so
1) does the βfollowersβ example from the Convex Ents docs work for this use case of replying?
2) if not, does a fake, but technically many:many junction table work better than this nested query approach you wrote?
Recap:
Problem: One message can be a reply to 0 or 1 other message. 1 message can have many replies.
This is an assymetrical, self-directed, optional 1:many edge.
Not directly supported with Ents, but the workarounds are either:
1. Use a field as @FleetAdmiralJakob π π π has done, and read the "parent" message manually. Most likely you will want to index the field so that you can get a query for replies of message X. This is the cheapest approach, works well, and is what you'd do in vanilla Convex as well.
2. Use a many:many edge. Enforce the uniqueness when writing a reply. Then the "reply" relationship will be stored in a separate table.
Here I'd probably recommend sticking with the first approach, unless you see a possibility of the edge changing from 1:many to many:many in the future.