-
Notifications
You must be signed in to change notification settings - Fork 81
Open
Description
I've made a function that allows one to just pass an object in order to filter results.
It looks like this:
/**
* Generates a dynamic filter function for ElectroDB entities based on provided filter criteria.
* The returned function can be used to create filter expressions for querying the database.
*
* @param filters - An object where keys are attribute names and values are the values to filter by.
* @template T - The type of the entity being filtered.
* @returns A function that takes an attribute accessor and operations object, returning a filter expression string.
* @example
* MyEntity.query({ id: 'e51685dc-f8e6-4c05-b7cf-1d6c22d16bfd' })
* .where(dynamicFilter<MyEntity>({ someAttr: 'a value', isActive: true }))
* .go();
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function dynamicFilter<T>(filters: Record<string, unknown>): (attr: any, ops: any) => string {
return (attr, { eq }) => {
return Object.entries(filters)
.map(([key, value]) => {
if (/\./.test(key)) {
// Use Function constructor to safely access nested property on attr object
const accessor = (0, eval)(`(attr) => attr.${key}`)(attr);
return eq(accessor, value);
}
return eq(attr[key as keyof T], value);
})
.join(' AND ');
};
}As you can see from the example in the jsdoc, you can run use it something like this:
MyEntity.query({ id: 'e51685dc-f8e6-4c05-b7cf-1d6c22d16bfd' })
.where(dynamicFilter<MyEntity>({ someAttr: 'a value', isActive: true }))
.go();It actually works exactly as advertised, but, of course, it's really only useful for eq operations at the moment which is fine for my uses anyway.
I have 2 questions:
- Is this even necessary? Is there a built-in way to do something like
where({ foo: 'bar', 'deep.nested.attr': true })? - I'm still having trouble filtering on nested attributes though I think what I'm doing should "just work" since I'm effectively doing an
evalon'deep.nested.attr'to convert it toattr.deep.nested.attr. I get an error saying "cannot read properties of undefined (reading 'type')" and I can't quite figure out why. I have checked just directly tryingeq(attr.deep.nested.attr, value)and that also yields the same error so it doesn't seem to be an issue with the indirect eval.
If the answer to my first question is "no", is there a way to formerly request such a feature? One that does, in fact, support deeply-nested filtering. You're welcome to use any bit of the code above to achieve it, of course.
Amazing library, by the way!
Metadata
Metadata
Assignees
Labels
No labels