In this article I will show you how I managed to get the search results count into a REST service and why I wanted to do that.
Introduction
Back in August 2012 I posted this on Stackoverflow. I will answer the question there but I don’t feel like I have “answered” it, just worked around it.
How do I make the XPages REST control return the overall number of filtered matches?
http://stackoverflow.com/questions/11786930/how-do-i-make-the-xpages-rest-control-return-the-overall-number-of-filtered-matc
Problem
When you create a viewItemFileService REST service using the the ExtensionLibrary control you get a response which looks like this:
{
"@timestamp":"2013-03-12T23:25:57Z",
"@toplevelentries":1299,
"items":
[
{
"@entryid":"100-8DE5EBF5E35C17F285257B1B00254A8F",
"@unid":"8DE5EBF5E35C17F285257B1B00254A8F",
"firstname":"Benjamin",
"lastname":"Imran",
"address":"2112 Hall Street",
"city":"Las Vegas",
"state":"NV",
"zip":89121,
"country":"US",
"email":"Benjamin.A.Wayman@mailinator.com"
},
which is fine…and from that you can ascertain that there are 1299 documents in the view (@toplevelentries)
The problem is when you execute a search against this REST service (for example ‘[address] contains street’) you still get @toplevelentries: 1299
This causes me great angst when it comes to the EXTJS grids because I want to use the Infinite Scrolling capability. What that does is calculates based on the size of the view (1299) how large a scroll bar to create and then display 25 entries at a time and load them as necessary. This is really smart except after you have searched the REST service. The grid still thinks there are 1299 documents even when there is only a subset matching the search results. This causes a lot of blank scrolling 😦
In my example the search ‘[address] contains street’ returns 338 matches. But this causes the following to happen with the infinite grid

And that sucks. Also note 52 pages in the pager!!!!
The EXTJS code to get the number of documents in the service looks like this:
var store = Ext.create('Ext.data.Store', {
// allow the grid to interact with the paging scroller by buffering
buffered: true,
pageSize: 25,
leadingBufferZone: 25,
autoLoad: true,
autoDestroy: true,
autoSync: true,
model: 'Person',
proxy: {
type: 'rest',
url: 'xRestService3.xsp/marky?count=25',
reader: {
type: 'json',
root: 'items',
totalProperty : '@toplevelentries' // This is the determining value
},
writer: {
type: 'json'
}
}
});
And as you can see form the code @toplevelentries is always 1299
So how do we get the 338 number to the grid without causing:
- Some major hacktastic, back end to front end, extra ajax calls, and redrawing the grid on the fly shenanigans
- Manually re-writting the REST service from scratch (which I could do but would cause much pain and suffering)
- Performance issues with XPiNC connecting to the server
- My eyes to bleed…..
This has baffled me for months and here’s how I got around it.
Solution
In the REST service you can create a custom column. In this case we are just returning the requestScope value for markyCount in the column “theRealCount”:
<xe:this.columns>
<xe:restViewColumn name="theRealCount">
<xe:this.value>
<![CDATA[#{javascript: return requestScope.get("markyCount")}]]>
</xe:this.value>
</xe:restViewColumn>
</xe:this.columns>
And markyCount is going to be the 338 value from the search. So how do we get that?
The REST service has an id value which can be computed – and I really don’t care what the id is because I am not binding it to a control on the form. So I used the opportunity for some server side computation of the id to create a little FTSearch.
In the example below I am simply getting the view used by the REST service (byFirstName) doing an FTsearch on it and then putting the count in the markyCount requestScope.
<xe:this.id>
<![CDATA[${javascript:
var theView:NotesView = database.getView("byFirstName")
var count = theView.FTSearch("[address] contains street");
requestScope.put("markyCount", count)
return "searchMe" //irrelevant value
}
]]>
</xe:this.id>
So what this does is create a REST service output which looks like this:
{
"@timestamp":"2013-03-12T23:25:57Z",
"@toplevelentries":1299,
"items":
[
{
"@entryid":"100-8DE5EBF5E35C17F285257B1B00254A8F",
"@unid":"8DE5EBF5E35C17F285257B1B00254A8F",
"firstname":"Benjamin",
"lastname":"Imran",
"address":"2112 Hall Street",
"city":"Las Vegas",
"state":"NV",
"zip":89121,
"country":"US",
"email":"Benjamin.A.Wayman@mailinator.com",
"theRealCount": 338 //this is the new column
},
Note theRealCount column with 338 in it. This is then added to every column output by the REST service. So yes the downside is that we are adding computation and output data size to the feed but it appears to make an insignificant amount of difference to the output speed of the service.
We then change the EXTJS code to look at the theRealCount value in the first Item and not @toplevelentries
var store = Ext.create('Ext.data.Store', {
// allow the grid to interact with the paging scroller by buffering
buffered: true,
pageSize: 25,
leadingBufferZone: 25,
autoLoad: true,
autoDestroy: true,
autoSync: true,
model: 'Person',
proxy: {
type: 'rest',
url: 'xRestService3.xsp/marky?count=25',
reader: {
type: 'json',
root: 'items',
totalProperty : 'items[0].theRealCount' // This is the determining value
},
writer: {
type: 'json'
}
}
});
And we get this – no more blank lines and 14 pages in the pager 🙂
