ent filtering
trying to do this but it never returns a result unless args.name is null, tried several variations. Looked through the saas starter for examples like this. the goal is to find any channel names so you cant enter a duplicate name within the same team.
const channel = await ctx.table("teams")
.get(args.teamId)
.edge("chatChannels")
.filter((q) => q.gt(q.field("name"), args.name));
---
chatChannels: defineEnt({
name: v.string(),
})
.index("name", ["name"]) <- added this too
.edge("team")
.edges("chatMessages", { ref: true }),
---
orginal code:
const channel = await ctx.db
.query("chatChannels")
.filter((q) => q.eq(q.field("name"), name))
.filter((q) => q.eq(q.field("teams"), teamId))
.first();
28 Replies
It sounds like you just want to return all of the existing channel names for the team, why the filter?
I'm checking for uniqueness of the channels name
basically just a isunqiue internal query to stop the user from duplicating channel names
Reading Ents from the Database - Convex Ents
Relations, default values, unique fields and more for Convex
Looks like you want that, except using an edge
But I don't know if what's returned there has a
get
method
disregard that, wrong thing
this is really simple to do in a regular convex function, trying to figure out the ents way
Yeah I guess just use .eq()
, although that's inefficient and you should just be able to index and call .unique()
.
That looks like:
That will get you the channel by that name or null
Still figuring out how to do this with just an index via ents
Does chatChannels
table have a teamId
field?Yeah, with ents from my understanding the edge("team") makes the teamId and i see it in the blank schema
changing it from q.qt to q.eq fixed it
Yeah, but you're fetching every channel when you only need one. Probably fine for now if you're early on, but I want to understand the proper solution and leave it here for others at least. Need to improve my Entish lol
its only returning a single channel name, the one im attempting to search for
In a plain convex function that looks like this:
It's fetching all of them from the db, and then basically using a js filter to remove all except the one you want
Again, 100% effective for your immediate purpose, but a simple index does this with the efficiency of a point query.
and it still queries a lot if i use .unique too
If you use a filter like my last bit of code there, and the name/teamid combo is unique in your database, the index will contain 0 or 1 rows
Any other approach has to scan more rows, likely all of the channels for a given team. Which, again, is totally fine! I just want to leave the actual right answer here for others that find it in the future.
For others running into this the tradeoff could be an issue.
well its at least not giving me all results across all teams, so the hack is worthy for the moment.
100%!
Isn't even a hack really, just not perfectly efficient, more than fine for most cases
Would you mind trying this? I'm betting it will show a typescript error right away anyhow, but curious if it works:
it doesn't, it was something i was trying before
ah okay
alright @Michal Srb I'm throwing in the towel. What am I missing?
in a perfect world syntax wise, const channel = await ctx.table("chatChannels")
.get("team", args.teamId)
.get('name', args.name)
@Michal Srb tl;dr: what's the Ent way to do this:
Yeah using
table('teams')
to get chat channels feels like indirectionwell it saves code other places
no I'm agreeing with you
your example is closer to what I would expect, using
ctx.table('chatChannels')
since that's what you're after, and that's how the underlying convex query should work@erquhart it is
But it's been blocked by a TS bug and is currently sitting on a branch, see
https://github.com/xixixao/convex-ents/issues/7
So meanwhile the normal approach works fine:
as documented here: https://labs.convex.dev/convex-ents/read#listing-ents-filtered-by-index
GitHub
get() with index should allow indexes with multiple fields · Issue ...
It should be possible to use a compound index to query unique ents: ctx.table("users").get("firstNameLastName", firstName, lastName) I had trouble getting the types to oblige wh...
Reading Ents from the Database - Convex Ents
Relations, default values, unique fields and more for Convex
Ah, did not realize
.table()
takes more args, that makes a lot of sense. So with this signature you're effectively just dropping straight down to ctx.db()
right?
Oh no you're still using .get()
though
argh looking at the wrong thing nvm lol
got it(the viaradic get() call will also translate to the exact same ctx.db query. It's all just syntactic sugar)
Okay that's really handy
This does work, in my efforts to reduce the use of by_ in the chatchannels schema: .index("teamId_name", ["teamId", "name"]) gave only "compile time" typescript errors and .index("by_teamId_name", ["teamId", "name"]) didn't. Just thought that was worth noting if someone else vists this thread.
@ampp The index name should not lead to typescript errors. What probably happened is that you changed two files (schema and functions), then saved only one of them, so the TypeScript in your terminal showed you an error.
I suggest during development to use
npx convex dev --typecheck=disable
to avoid being confused by the terminal.@ampp @erquhart this has been released, make sure you're on convex-ents@latest and using TypeScript 5.4 or later:
Docs: https://labs.convex.dev/convex-ents/read#reading-a-single-ent-via-a-compound-index
Reading Ents from the Database - Convex Ents
Relations, default values, unique fields and more for Convex
Hey just circling back to this thread - having a similar issue with filtering an edge with ents. I am on convex-ents@latest and Typescript 5.7.
here is my query:
The .filter is throwing a Type Error:
Parameter 'q' implicitly has an 'any' type.
Thanks all.@gabrielw I would open a separate support post for your specific issue, this is an old one that's already resolved and doesn't mention the error you're encountering.
Thanks @erquhart , I opened up a support post