Trouble with equality predicate

const emptyFields = await ctx.db
.query("bookmarks")
.withSearchIndex("by_userId", q =>
q.search("userId", userId).eq("embedding", undefined || [] || null), // the fields with [] are selected correctly. but the fields that are "unset" are not selected. how can i select them?
)
.collect();
const emptyFields = await ctx.db
.query("bookmarks")
.withSearchIndex("by_userId", q =>
q.search("userId", userId).eq("embedding", undefined || [] || null), // the fields with [] are selected correctly. but the fields that are "unset" are not selected. how can i select them?
)
.collect();
13 Replies
RJ
RJ2y ago
undefined || [] || null is an expression which is being evaluated to a single value ([], apparently). So what you have is equivalent to:
const emptyFields = await ctx.db
.query("bookmarks")
.withSearchIndex("by_userId", q =>
q.search("userId", userId).eq("embedding", []),
)
.collect();
const emptyFields = await ctx.db
.query("bookmarks")
.withSearchIndex("by_userId", q =>
q.search("userId", userId).eq("embedding", []),
)
.collect();
ashuvssut (ashu)
ashuvssut (ashu)OP2y ago
Oh. how can i select "embedding" field document whose value is "unset" ?
RJ
RJ2y ago
See https://docs.convex.dev/database/reading-data#combining-operators for how to OR those equality checks I don't remember, I think undefined might be correct (I am not a Convex employee, who would know the answer!) You could give that a shot!
lee
lee2y ago
undefined is correct for finding unset fields. you can do an OR in a filter, but if you want to use the search index to do the filtering (more efficient) you would have to do two fetches and combine them
const emptyFields = await ctx.db
.query("bookmarks")
.withSearchIndex("by_userId", q =>
q.search("userId", userId).eq("embedding", []),
)
.collect();
const unsetFields = await ctx.db
.query("bookmarks")
.withSearchIndex("by_userId", q =>
q.search("userId", userId).eq("embedding", undefined),
)
.collect();
const allResults = [...emptyFields, ...unsetFields];
const emptyFields = await ctx.db
.query("bookmarks")
.withSearchIndex("by_userId", q =>
q.search("userId", userId).eq("embedding", []),
)
.collect();
const unsetFields = await ctx.db
.query("bookmarks")
.withSearchIndex("by_userId", q =>
q.search("userId", userId).eq("embedding", undefined),
)
.collect();
const allResults = [...emptyFields, ...unsetFields];
ashuvssut (ashu)
ashuvssut (ashu)OP2y ago
thx!! What if I want to do something other than .eq with searchIndex "embedding", Actually I wanted something like .notEq to use with searchIndex "embedding" for example, "embedding" is notEq empty array ([]) I think I have to use .filter in this case do you know a better way to do with searchIndex?
lee
lee2y ago
quick question, are you sure this should be a search index? "userId" sounds like a field that you could check with a regular index
ashuvssut (ashu)
ashuvssut (ashu)OP2y ago
userId is not a document stored in any Table, it is not related to any convex db table. i get a userId from clerk
ashuvssut (ashu)
ashuvssut (ashu)OP2y ago
here's the db schema. there are 2 tables
No description
lee
lee2y ago
do you want to check that the "userId" field exactly matches userId ? .searchIndex(...) does full-text search https://docs.convex.dev/text-search which does not sound like what you want. .index(...) may be more appropriate
Full Text Search | Convex Developer Hub
Run search queries over your Convex documents
ashuvssut (ashu)
ashuvssut (ashu)OP2y ago
Oh understood thanks! I liked you searchIndex trick that you showed above. Do you have any searchIndex trick for this use case? (I want to perform something like .notEq) I think I have to use .filter
lee
lee2y ago
if you can use a regular index, you can do a similar trick with .withIndex("by_userId", q => q.eq("userId", userId).gt("embedding", []) and then .withIndex("by_userId", q => q.eq("userId", userId).lt("embedding", []) and then combine them i brought up the search index thing because search indexes do not support .gt and .lt, but regular indexes do. and notEq is equivalent to a union of gt and lt
ashuvssut (ashu)
ashuvssut (ashu)OP2y ago
alright! got it thanks
Michal Srb
Michal Srb2y ago
I'd add that it's likely a single user won't have many associated bookmarks, and so excluding them from the database query won't help much . I would exclude the user after you .collect() all your results:
const bookmarks = (await ctx.db.query("bookmarks").collect())
.filter(bookmark => bookmark.userId !== userId);
const bookmarks = (await ctx.db.query("bookmarks").collect())
.filter(bookmark => bookmark.userId !== userId);

Did you find this page helpful?