I have a database existing of user docs
. Sample user object is as follows:
user {
id: string,
name: string,
town: string,
city: string,
country: string,
filter: ["town", "city"] // array of strings
}
I want to get users where their id’s don’t include spesific ids (which is a must), also some other query parameters. I have a filter field which is an array (its structure can be changed for doing the purpose of the query), consisting of items ["town", "city", "country"]
. Its alternative values are ["town"]
, ["town","city"]
, ["town","city","country"]
and ["noone"]
. There is a contains order for filtering: country > city > town. I mean parent is country, its children are cities, its children are towns. I firstly tried with setting the filter
field as string, but I got error from firebase telling OR cannot be used with NOT-IN. Then I transformed the filter
field to an array. But again due to limitations of firebase, I cannot obtain what I try to. Maybe my issue is about not creating the right skeleton data structure about filter
field.
What I need to do is exactly querying these: if I want to query where filter
is “town”, it should bring all users with same “town” names whose filter value is not [“noone”], but can have values of [“town”], [“town”, “city”] or [“town”,”city”,”country”].
If my filter
is “city”, it should bring all users with same “city” named users whose filter
value is not ["noone"]
or ["town"]
, but if queried user’s filter value is [“town”] and having same town with the querying user, than it should be included this in results.
If my filter
is “country” it should bring all users with same “country” name, also including users having the same city names and having same town names whose filter value is not set to [“noone”]. But this result should bring users whose filter
values are “town” who are in the same town with querying user, also whose filter
values are “city” who are in the same city with querying user.
I hope I could explain what I try to achieve, briefly querying users by applying mutual filter values. What I tried is:
let locFilter, filterVal
if (user.filter.includes("country")) {
locFilter = or(where("country", "==", user.country), where("city", "==", user.city), where("town", "==", user.town))
filterVal = ["town", "city", "country"] } // this logic is faulty when querying user's town or city is same as queried user's town or city while his filterVal is whether ["town"] or ["town", "city"]. But I couldn't find a better way
else if (user.filter.includes("city")) {
locFilter = or(where("city", "==", user.city), where("town", "==", user.town))
filterVal = ["town", "city"] } // this logic is faulty when querying user's city is same as queried user's city while his filterVal is whether ["town"] or ["town", "city", "country"]. But I couldn't find a better way
else if (user.filter.includes("town")) {
locFilter = where("town", "==", user.town)
filterVal = ["town"] } // this logic is faulty when querying user's town is same as queried user's town while his filterVal is whether ["town", "city"] or ["town", "city", "country"]. But I couldn't find a better way
await getDocs(query(collection(db, "users"),
and(
where("id","not-in", [...blockedIds, ...deletedIds]),
where("filter", "array-contains-any", filterVal),
locFilter
)))
but this gives error, because of firebase limitations (NOT-IN cannot be used with 'IN', 'ARRAY_CONTAINS' or 'OR')
. Should I change my data structure for firebase to query without errors? If so, how? Data structure of filter
field should be rearranged other than array
for this aim? Can someone help?