How to return the total number of rows of a collection before/ after filtering

Hi

I have a collection and a number of filters. First when I start the page, I want to display the total number of rows of the collection. Although this sounds pretty simple, for some reason my code is not working.

$w.onReady(() => {

let myTest=getNumberOfResults();
console.log(myTest)
$w(‘#text26’).text =getNumberOfResults() //+ " items"
}

function getNumberOfResults () {
wixData.query(“Wedding_Database”)
.find()
.then( (results) => {
let resultCount = results.totalCount.toString();
console.log(resultCount)
return resultCount

} ) ;
}

Within the function, the console.log(resultCount) works and returns the right value. However the console.log(myTest) gives me undefined. I tried differetn things (.value, etc.) but nothing works. Any idea where the issue might come from?

I did it first without the function, where it worked perfectly. However I need the functions as I want to count the number of results also after I applied some filters and for this I thought having a function is easier than having the code multiple times.

Thanks a lot!

I can’t see the filters in your code, and it depends on how you filter (by direct query? dataset.setFilter() ? running JS code to filter the full results array? ).

I don’t have any filters yet. Here I want to find the total rows of the database. But this is already not working. Filter will be the next step.

@svenstrebel even here it depends on what exactly you want.
You didn’t set query.limit(1000) so by default you get maximum 50 results.
Do you want to see the number of the returned results (max 50) or the number of the total entries in your collection?

@jonatandor35 the total number of entries (which is more than 1000)

I changed the code to:

function getNumberOfResults () {
wixData.query(“Wedding_Database”)
.limit(1000)
.find()
.then( (results) => {
let resultCount = results.totalCount.toString();
console.log(resultCount)
return resultCount

} ) ;
}

But I still get an undefined if I run the function

this here “console.log(resultCount)” returns 1001, which is correct

@svenstrebel see:
https://www.wix.com/corvid/reference/wix-data.WixDataAggregate.html#count

@jonatandor35 thanks, but what I don’t get is why is the “console.log(resultCount)” returning the right results, but if I run the function with this:

$w.onReady(() => { let myTest=getNumberOfResults(); console.log(myTest)
$w(’ #text26 ').text =getNumberOfResults() //+ " items" }

It is not

any idea what is causing the issue? Is my function not correct or the return statement?

@svenstrebel that’s because you run the console.log() before you get the Promise results.

@jonatandor35 And how can I change the code so that the function returns the value? In my logic, whatever the console.log() inside the function shows, should also be returned by the function. And I don’t understand why it is not.

This code here works:

$w.onReady(() => {
wixData.query(“Wedding_Database”)
.limit(1000)
.find()
.then( (results) => {
let resultCount = results.totalCount.toString();
console.log(resultCount)

$w(‘#text26’).text = resultCount + " items"
} ) ;
}

@svenstrebel you can either put the console.log() and the text assignment inside the .then() block:

function getNumberOfResults () {
wixData.query("Wedding_Database") .find() 
.then( (results) => { 
  let resultCount = results.totalCount.toString(); 
   console.log(resultCount) 
   $w('#text26').text =getNumberOfResults() //+ " items" 
  } ) ; 
}

or use your code with an async function like this:

$w.onReady(async function ()  { 
    let myTest = await getNumberOfResults();
    console.log(myTest)
    $w('#text26').text =getNumberOfResults() //+ " items" 
})

Try to see if it works

@jonatandor35 Got it, thank you

On top of that, I want to update the number while filtering. I tried this, which is inside the fiter:

$w(‘#dataset1’).setFilter(newFilter);
//Get number of element
let resultCount = $w(‘#dataset1’).setFilter(newFilter).totalCount.toString();
$w(‘#text26’).text = resultCount + " Items"

.totalCount doesn’t work with the filter. I looked at aggregate but from the code it doesn’t look like I could combine the two.

If I have a filter, which works fine, is there a commend to get the number of filtered rows?

@svenstrebel

  1. I think it’s not a good idea to use direct query (as you posted above) and to use dataset for filtering, because it means you go to the backend one extra time (and you should think about the performance). Why don’t you use dataset only?
  2. as for your question, you should try something like:
$w('#dataset1').setFilter(newFilter)
.then($w('#dataset1').refresh())
.then(() =>{
    let resultCount = $w('#dataset1').getTotalCount().toString();
    $w('#text26').text = resultCount + " Items";
}).catch(err => err);

Fixed (I missed a parenthesis)

@jonatandor35 : Code works, thanks you!!

In terms of datase1 vs. Wedding_Database

I am acutally facing performance issues. The collection has 1001 rows, the repeater shows 12 elements including a picture for each. I have 8 filters and it takes forever to load. If I understand you correctly, you would only use database1 and not Wedding_Database, correct?

Do you have some other tricks how to improve the performance of repeaters?

@svenstrebel I recommended to only use the data set because it’s probably faster than using both and it’s easier for me to explain how to do it.
But it’s not necessarily the best performance. Maybe running direct queries for filtering will be even better.

@jonatandor35 Ok and do you have a recommendation what to use? Direct queries would be on Wedding_Database correct?

Can I use the same comands or is there a page that explains which commands are for direct queries vs. queries on the dataset?

@svenstrebel first of all, I stopped using datasets a long time ago, so maybe the current performance is good enough (you should ask someone who uses it.
second for filtering by direct quesries you should use:
.eq()
.gt()
.etc…
something like:

wixData.query('My Collection')
.eq('title', $w('#input1').value);
.gt('quantity', 3)
.lt('quantity', 30)
.isNotEmpty('price')
.limit(1000)
.find()
.then( r=> {

})

and if you use it, don;t forget to remove the dataset from the page

@jonatandor35 Thank you! I tried this code here:

function filter2(myPriceRange) {
wixData.query(“Wedding_Database”)
.eq(“price”, myPriceRange)
.limit(1000)
.find()
.then( r=> { let myNewResults = r.items;

$w(‘#repeater1’).data=myNewResults;
})
}

The repeater is very slow and in most cases does not even load (the database contacts 1000 rows). Any idea why the performance is that bad?

@svenstrebel repeaters are slow, That’s a known problem.
You should not assign 1000 items to the repeater together.
There’re some solutions:

  1. divide the results array into groups of 20 (each of the in a different array), assign the first array to the repeater, add “Next” and “Back” buttons, once the user clicks “Next” assign the next array to the repeater.
  2. set an interval and every 2 seconds assign 10 more to the repeater. Something like:
function filter2(myPriceRange) {
wixData.query("Wedding_Database") 
.eq("price", myPriceRange).limit(1000).find()
 .then( r=> { 
let items = r.items; 
let newItems = items.splice(0, 10);
let toAssign = [...newItems];
$w('#repeater1').data = toAssign; 
let assignData = setIterval(() => {populateRepeater}, 2000);
function populateRepeater(){
if(items.length > 0) {
newItems = items.splice(0, 10);
toAssign.push(newItems);
toAssign = toAssign.flat();
$w('#repeater1').data = toAssign; 
} else {clearInterval(assignData);}
}
}) 
}

But really if it’s 1000 results you should consider show it in different pages (the first option)