Reputation: 302
To put simply. It is a filtering problem that i am having with Firestore. Take this model as an example:
Collection: Room
- Document#1
- query_role: Array - Limit 10
- query_user: Array - Limit 10
- players: Array<Object> [{
playerId: string
user: Object<id, firstname, lastname, ...>
role: Object<id, name, ...>
}]
...
My application has a page called rooms that anyone could use to search for (you guessed it) rooms.
With filters to narrow down the type of room they can enter but for this example, we'll just use role as the only filter. Simple stuff or so I thought.
The logic behind the search/filter page are to:
Collection: Room
- Document#1
- query_role: ['111', '222', '333', '333']
- query_user: ['user1', 'user2', 'user3', false, false, false, false, false, false, false]
- players: [{
playerId: 'djs123d21sSd213r'
user: null
role: {
id: '111',
value: 'Mafia'
...
},
...
}]
...
Every role that is created for this room is inserted into the players->role
with the user set to null
. The role is then inserted into query_roles
to use as a filter on the page if a user chooses to search by available roles:
.where('query_roles', 'array-contains', role)
Now the problem is, with firestore. You can only use array-contains
once in a query. I keep getting errors like this: A maximum of 1 \'ARRAY_CONTAINS\' filter is allowed.'
. The other array-contains
as i've mentioned before, is being used on query_users
to find rooms that still have space by doing:
.where('query_user`, 'array-contains', false)
I cant put them in an object like so:
{
user1: true,
user2: true,
false: true,
false :true
}
since all of those false
would slap into one field and it would be the same with roles. Since there can be multiple roles that are the same, it would merge into one field.
The only way I can think of is manually setting up a flag that says full: true|false
that will be used to determine if a room is full or not. I'd still need to use the query_user
because in the application i use it to search for all Rooms a specific user is in.
I am writing to see if there are any alternative ways anyone else can think of without messing about with creating flags. Long question, but I appreciate you reading up until here.
Upvotes: 0
Views: 981
Reputation: 138824
Find all rooms that still have space in them
To solve this you can simply add into your room document two new properties. One would be named numberOfRoles
and the other one numberOfUsers
. Once you add a new role to the query_role
array increase the value of numberOfRoles
by one and every time you add a new user to the query_user
array increase the value of numberOfUsers
by one. In this way you can simply query your rooms collection using:
roomsRef.where('numberOfRoles', '<=', 10).where('numberOfUsers', '<=', 10)
Chaning multimple array-contains
functions is not allowed in Coud Firestore but chaining multiple where()
calls will work perfectly fine.
Use the filter to find rooms that still have a certain role in them (e.g. Mafia, Doctor, Villager, etc...) that aren't assigned to any users
Once you get a positive result from the above query then you can get the content of your query_role
array and see the available rolls.
Every role that is created for this room is inserted into the players->role with the user set to
null
.
There's no need for that anymore.
The only way i can think of is manually setting up a flag that says full: true|false that will be used to determine if a room is full or not. I'd still need to use the query_user because in the application i use it to search for all Rooms a specific user is in.
Setting a flag to true|false
will not solve your entire problem. Please note that if you want to search for a specific user in the query_user
array you can still do that since you perform only a single query using the array-contains
operator.
Upvotes: 1