Filter elements with more than one dataSlot/Category


#1

Hello,

I already created a page where a list grid shows my Firebase database. There are several elements with different categories. Now I would like to add several filters so I can reduce what is shown to the user according to these filters.

I followed the steps about the script to filter elements, but instead of a search bar I made it with a picker. It works fine. My problem comes when I want to associate another picker in order to filter a different category. I tried to change the script adding the new dataSlot in the stringfiltered and the category in the appropriate place, but it turns out that it only works the second picker (filter) and not the first one.

I guess I am doing something wrong with the script. How should I implement the script?

In the other hand, I understand that I could create these filters in the server side pointing the information to filter in the datasheet section but I don’t know how to do it.

Thank you.


#2

Hi,

This is more about Firebase than React Studio. Anyway Firebase started to support “In queries” which allows you to “filter” collection based on multiple filters and React Studio’s plugin supports this as well. Here’s a good read about it:

I would not suggest to use list script because it has nothing to do how the data is loaded in server and simply would not work on larger data sets.

You just need to edit the Data slot value so that it contains all selected filters in comma separated list. Something like this:


#3

Thank you so much for your answer. I have tried in several ways and I am not able to make it work. Let me show what I have so far:

  1. I have placed two pickers in the filter bar. Each one of them takes its reference from a different column from a sheet and show two different categories each element may belong to. Both pickers save the data in the dataslot “ds_SlotFilter” and I have written the script to separate with comma only in the second picker, because when I did it in both I got an error.

  2. Then I have my sheet that shows all the items that I want to be shown, only to be filtered after picking one value in any of the pickers. So I use the “array-contains-any” option but it doesn’t work.

What I get instead is that no element is shown. Not even when I select any value in any picker.

Another thing to ask. I can select a value from the picker, but how would I remove the information from the dataSlot if I want to show all the items again?

Thank you!


#4

Hi,

I’d suggest that you check the Firestore docs: https://firebase.google.com/docs/firestore/query-data/queries

I’m quite sure you cannot make In and array-comtains-any clauses more than one column at a time.

What comes to erasing the Data slot value you just need to write a script to clear the Data slot or use Clear interaction in Save data interaction.


#5

Now that I achieved to get working the first filter, I added the second one and followed the steps adding the script. And there is something I must change to make it work because the second filter is not working and the console shows the following error:

** error creating firebase query object from ‘where(“categories”,“array-contains-any”,[“Principiante,“Pop/Rock””])’: SyntaxError: Unexpected identifier

Apparently, the quotation marks that were destined to the first identifier are closing at the end of the array instead of the end of the first value. I have tried to change the script of the second filter but my knowledge is limited and I don’t get to make it work. This is the script that I wrote in the second filter:

let prevFilters=this.props.appActions.dataSlots[“ds_SlotLevel”];
return prevFilters +",""+input+""";

I leave also here the query that I have in the data sheet, because I believe it has some impact in the output:

where(“categories”,“array-contains-any”,["$slot(ds_SlotLevel)"])

Thank you!


#6

Take away the quotation marks around the data slot in Query field.

Here is what I had on my project:

Query inb Data sheet:

where("categories",
"array-contains-any",
[$slot("ds_SlotSelectedCatagories")]
)

Button script which adds new filter to data slot:

var selectedCategories="";
 selectedCategories=this.props.appActions.dataSlots['ds_SlotSelectedCatagories'];
//
// Update data slot value
if (selectedCategories != ""){
input = selectedCategories + ",'" + input +"'";
} else
{
input = "'" + input +"'";
}

return input;

And finally button which removes selected filter from data slot

//We are deleting the category from the selected categories
//Simply delete the category form the string

var selectedCategories="";
selectedCategories=this.props.appActions.dataSlots['ds_SlotSelectedCatagories'];
input=selectedCategories.replace("'"+input+"'","");

//Check if string ends with "," and delete "," in that case
if (input.endsWith(",")) {
	input=input.substring(0, input.length - 1);
}

//Check if string starts with "," and delete "," in that case
if (input.startsWith(",")) {
	input=input.substring(1, input.length);
}

return input;

#7

If I remove the quotation marks in the query the first filter stops working. This is the console log:

** error creating firebase query object from ‘where(“categories”,
“array-contains-any”,
[Principiante]
)’: ReferenceError: Principiante is not defined

And of course, the second value doesn’t work either:

** error creating firebase query object from ‘where(“categories”,
“array-contains-any”,
[undefined,‘Pop/Rock’]
)’: FirebaseError: Function Query.where() called with invalid data.


#8

It definitely will because you’re not adding ’ to first item. Check my code example:

if (selectedCategories != ""){
input = selectedCategories + ",'" + input +"'";
} else
{
input = "'" + input +"'";
}

If data slot value is empty ’ marks are added around the filter (first filter).


#9

For the first filter, if I remove the quotation marks from the query, the value that I enter is not recognized because it needs those quotation marks. I tried to manually write the quotation marks in the default value of the slot and it worked. So I am guessing I need to remove the quotation marks from the query field because when I have several values, those quotation marks would be for all of the values. But now I need to do something about the first value so that when the user pick a value, it goes in with quotation marks. The way to do it is through a script?


#10

What you need is to create this kind of string into data slot: loading firebase data for ‘cars’ with query:

'filter1','filter2','filter3'

So you just need to figure out how to create a script which creates that kind of string into Data slot. The full query looks like this in my console:

loading firebase data for 'cars' with query: where("categories",
"array-contains-any",
['diesel','red','sedan']
)

#11

I finally got it working. It is not exactly what I had in mind but it ok. As my Javascript knowledge is limited, I don’t know how to get what I want but I will eventually as I keep learning. It is fine as it is now. I placed a button that clears the data Slot value and that allows me to filter again and not keeping adding values with the pickers.

Thank you so much for your help and great work with the software!


#12

I achieved to make it work with “array-contains-any” but then I decided that I want to show just the documents with ALL words in the array, and not all elements with ANY word in the array. So I thought it would be easy, I just used “array-contains” and I don’t know why it didn’t work. No elements are shown. I also tried the “in” query but the same issue. No documents are shown. I went to the developer console and no error appears, the array is properly done. Maybe I am missing something?


#13

Just check that the query looks ok in console and check if the query is really ok and you have some documents which will meet the ‘ALL’ written exactly same in the DB. Otherwise its impossible to guess the issue here. Just start debugging the issue by checking that the query seems right in Console.


#14

Here I am again dealing with this. I am sorry if I am being persistent but I believe I am getting close to the solution. I went ahead to try several things and check with the developer console and this is the situation:

  • The closer I have gotten to the desire result is when I use the query:
    where("categories","array-contains-any",[$slot("ds_Filter")])
    With that, both pickers I have placed (one for level and one for music style) are working. The problem is that it shows all elements/documents that contains any of the values, and what I want is to show just documents with both values in the array. So I guessed I have to change “array-contains-any” for “array-contains”.

  • When I change for “array-contains”, it doesn’t work leaving the query as before. I need to remove the brackets around $slot(“ds_Filter”). Because if I leave it like this:
    where("categories","array-contains",[$slot("ds_Filter")])
    When I pick the first value, the console shows me:

loading firebase data for ‘arreglos’ with query: where(“categories”,
“array-contains”,
[“Principiante”]
)

And no document appears. Obviously, it doesn’t show anything either when I pick a second value in the other picker:

loading firebase data for ‘arreglos’ with query: where(“categories”,
“array-contains”,
[“Principiante”,“Pop/Rock”]
)

So I assumed the problem was the brackets. I removed them and now the first picker works, but not the second one. So now my query is like this:

where("categories","array-contains",$slot("ds_Filter"))

When I select a value in the first filter, it shows all elements with that value in the “categories” array. It works. But when I select another value from the second picker, the console gives me an error:

** error creating firebase query object from ‘where(“categories”,
“array-contains”,
“Principiante”,“Pop/Rock”
)’: FirebaseError: Function Query.where() requires 3 arguments, but was called with 4 arguments.

So, how can I make it to make it work the way I want? if I select a value in the first picker, it shows all elements with that in the array. If I select another value in the second picker, it must show all documents with both values in the array.

Thank you.


#15

Hi,

If you take a look Firebase’s documentation the “array-contains-any” or “in” won’t support this kind of “and” query. They are always “or” so the query will check if any of the criteria is found.

https://firebase.google.com/docs/firestore/query-data/queries

If you want to make multiple .where query then you maybe can do compound query but based on the documentation compound queries cannot include array-contains-any or in.


#16

Thank you so much for your answer. I will keep digging into it and see if I can achieve it. In order to fine tune my query, I still don’t get what I had in mind with just one picker and I don’t know if it isn’t possible.

What I would like to get is that all documents in the collection are shown in the first place without the user doing anything. Then I have placed a picker in the top bar and the idea is that the user can filter those documents by several criteria. Each picker would refer to a different filter category. I am thinking about getting to work that way at least the first picker, and move on from there later. But right now I don’t know how to achieve that.

How would go if I want to filter/query the collection only after user has selected some value in the picker?


#17

I don’t have any other idea than write a script which checks the filter data slot and if the value is empty then change the list element’s data source to Data sheet which contains all items. If the filter data slot contains a value then use Data sheet with your filter query.

Something like this:

I added the script to List item’s Filter items script.

Here’s my quick Demo: https://neonto.cloud/u/friendlyeatsfilter

Anyway this is already quite far outside Studio’s scope. This kind of business logic is something you probably need to do directly in the code.


#18

Thank you so much. That is working perfectly. So I already have the entire collection and it is filtered only when the user picks a value. I would love to have another picker with the possibility to filter an additional category but as I am dealing so hard with it, I am going to leave right there and retake the challenge some time ahead. I am learning at the same time I am creating the project and probably I need to assimilate more concepts before approaching this.

Again, thank you.


#19

In my example I have two Data sheets: one without Query and one with the query. When user selects value from picker and saves the filter into Data slot then the list script takes care of which Data sheet is used as a data source for the list/grid.

As I previously mentioned the filtering with many categories is just something that Firebase is not supporting at the moment. If that is must have function then you need to choose some other backend.