Table paging in query results table - pagination

I have a query form with table in a page and I'm trying to use paging instead of using scroll to see all the data returned by the query.
I have found a link that explains how can I do it site1 and it works, but when I try to access one page ahead, for example page 400 or 1000 it takes too long to return that data.
I also have found another one site2 that explains that I have to change som properties in the VO of that data. I have tryed to use both simultaneous, only the second one but with no success.
Is there a way to do it that does not take too long to fetch the data?

Visit your iterator tree in the pageDef file and set the rangeSize on the iterator.
Also make sure to check VO definition as iterator changes wouldn't override VO settings.

I was able to put pagination to work, changing this
In the VO
Sector Tunning
All Rows;
In Batches of: 100
Component Table
Appearance / ScrollPolicy - page
Behaviour / AutoHeightRows - 0
Style / StyleClass - AFStretchWidth

Related

Alfresco webscript (js) and pagination

I have a question about the good way to use pagination with Alfresco.
I know the documentation (https://wiki.alfresco.com/wiki/4.0_JavaScript_API#Search_API)
and I use with success the query part.
I mean by that that I use the parameters maxItems and skipCount and they work the way I want.
This is an example of a query that I am doing :
var paging =
{
maxItems: 100,
skipCount: 0
};
var def =
{
query: "cm:name:test*"
page: paging
};
var results = search.query(def);
The problem is that, if I get the number of results I want (100 for example), I don't know how to get the maxResults of my query (I mean the total amount of result that Alfresco can give me with this query).
And I need this to :
know if there are more results
know how many pages of results are lasting
I'm using a workaround for the first need : I'm doing a query for (maxItems+1), and showing only maxItems. If I have maxItems+1, I know that there are more results. But this doesn't give me the total amount of result.
Do you have any idea ?
With the javascript search object you can't know if there are more items. This javascript object is backed by the class org.alfresco.repo.jscript.Search.java. As you can see the query method only returns the query results without any extra information. Compare it with org.alfresco.repo.links.LinkServiceImpl which gives you results wrapped in PagingResults.
So, as javacript search object doesn't provide hasMoreItems info, you need to perform some workaround, for instance first query without limits to know the total, and then apply pagination as desired.
You can find how many objects have been found by your query simply calling
results.length
paying attention to the fact that usually queries have a configured maximum result set of 1000 entries to save resources.
You can change this value by editing the <alfresco>/tomcat/webapps/alfresco/WEB_INF/classes/alfresco/repository.properties file.
So, but is an alternative to your solution, you can launch a query with no constraints and obtain the real value or the max results configured.
Then you can use this value to devise how many pages are available basing you calculation on the number of results for page.
Then dinamically pass the number of the current page to the builder of your query def and the results variable will contain the corresponding chunk of data.
In this SO post you can find more information about pagination.

Xpages how to sort preselected large amount data from view

I have a domino database with the following view:
Project_no Realization_date Author
1/2005 2015-01-02 Alex/Acme
3/2015 2015-02-20 John/Acme
33/2015 2016-06-20 Henry/Acme
44/2015 2015-02-13 John/Acme
...
Now I want to get all projects from this view that starts i.e with "3" (partial match), sort them by Realization_date descending and display first 1000 of them on Xpage.
View is large - some selection can give me 500.000 documents.
The FT search view option is not acceptable because it returns 5.000 docs only.
Creation of ArrayList or ListMap resulted with java out of memory exception (java Domino objects are recycled). Exceeding the memory may help of course but we have 30k users so it may be insufficient.
Do you have any ideas how can I achive this?
I think the key is goiong to be what the users want to do with the output, as Frantisek says.
If it's for an export, I'd export the data without sorting, then sort in the spreadsheet.
If it's for display, I would hope there's some paging involved, otherwise it will take a very long time to push the HTML from the server to the browser, so I'd recommend doing an FT Search on Project_no and Realization_date between certain ranges and "chunking" your requests. You'll need a manual pager to load the next set of results, but if you're expecting that many, you won't get a pager that calculates the total number of pages anyway.
Also, if it's an XAgent or displaying everything in one go, set viewState="nostate" on the relevant XPage. Otherwise, every request will get serialized to disk. So the results of your search get serialized to disk / memory, which is probably what's causing the Java memory issues you're seeing.
Remember FT_MAX_SEARCH_RESULTS notes.ini variable can be amended on the server to increase the (default) maximum from 5000.
500,000 is a very high set of results and is probably not going to make it very user-friendly for any subsequent actions on them. I'd probably also recommend restricting the search, e.g. forcing a separate entry of the "2015" portion or preventing entry of just one number, so it has to be e.g. "30" instead of just "3". That may also mean amending your view so the Project_no format displays as #Right("0000" + #Left(Project_no,"/"), 4), so users don't get 3, 30, 31, 32....300, 301, 302...., but can search for "003" and find just 30, 31, 32..., 39. It really depends on what the users are wanting to do and may require a bit of thinking outside the box, to quickly give them access to the targeted set of documents they want to action.
I would optimize data structure for your view. For example make a ArrayList<view entry>, that will represent the minimum information from your view. It mimics the index. The "view entry" is NOT Notes object (Document, ViewEntry), but a simplified POJO that will hold just enough information to sort it (via comparator) and show or lookup real data - for example Subject column to be shown and UNID to make a link to open that document.
This structure should fit into few hundred bytes per document. Troublesome part is to populate that structure - even with ViewNavigator it may take minutes to build such list.
Proper recycling should be ok but...
You could also "revert" to classic Domino URLS for ex ?yourviewname?ReadViewEntries&startkey=3&outputformat=JSON and render that JSON via Javascript UI component of some kind
If the filtering is based on partial match for the first sorted column, there's a pure Domino based solution. It requires that the Domino server is 8.5.3 or newer (view.resortView was introduced in 8.5.3), and that the realization_date column has click to sort.
Create a filtered collection with getAllEntriesByKey( key, false ) <-- partial match
Call view.resortView( "name_of_realization_date_column" )
Create a collection of all entries, now sorted by realization_date
Intersect the sorted collection with the filtered collection. This gives you the entries you want sorted by realization_date. E.g. sortedCollection.intersect( filteredCollection )
Pseudocode:
..
View view = currentDb.getView( "projectsView" );
view.setAutoUpdate( false );
ViewEntryCollection filteredCollection = view.getAllEntriesByKey( userFilter, False );
// Use index where view is sorted by realization_date
view.resortView( "realization_date" );
// All entries sorted by realization_date
ViewEntryCollection resortedCollection = view.getAllEntries();
resortedCollection.intersect( filteredCollection );
// resortedCollection now contains only the entries in filteredCollection, sorted by realization_date
..
I'm not certain if this would be faster than creating a custom data structure, but I would think it's worth to test :)

Does a Pager or Repeat Control expose the rowCount?

If I have on an Xpage a panel (say panelData) that has a data definition of a dominoView (say viewCollection) that is filtered and returns a group of documents. Then add a repeat control inside panelData (say repeatData) that is bound to viewCollection and the collection name is say rowData. Now add a Pager for repeatData. All works fine.
Now the pager has to be able to query repeatData and get the number of rows contained within the repeat. So my question is is there a way to get the rowCount directly from either repeatPager or repeatData without having to recompute the value.
stWissel suggests using viewCollection.getRowCount() here:
Getting the number of documents returned to from a viewEntry
but says that there could be a significant performance hit if there are a lot of documents in the collection because this method recounts the documents, but the pager and the repeat laready knows how many documents there are in the collection. Is there a lower level property that is excessible from either the Pager or the Repeat that does not require recounting all the documents in the collection?
What I'm trying to do is hide the pager if the rowCount is greater than the rowLimit. I have added the rowLimit as a customProperty to the Custom Control then set the rowLimit of the repeat to compositeData.rowLimit.
The View Container (ViewPanel, DataView etc) has the rows property that gives the number of rows to show at any one time. The dominoView will have the number of rows available to the pager, so you need to get a handle on that component, get its data model and query that. So getComponent("dataView1").getDataModel().getRowCount() will give you what you want without needing to query the underlying view twice.
I'd strongly recommend this blog post I wrote http://www.intec.co.uk/understanding-xpages-views/. It was a real revelation to understand how the various moving parts work.

Retrieving column values in filtered xpages view

I have a view defined on an xpage. I also have several filters (based on the columns) that the user can select and combine to filter the results in the view. I generate a query string based on this that I construct in dominoView.search (doing a complete refresh). What I would like to do is get the results of the search so that I can then update some counts displayed elsewhere on the page. I'm having a hard time figuring out where I can perform this logic, though. I'm trying to use view.getAllEntries() and then iterating over the collection. Sometimes it seems like it works, but other times I seem to be getting the unfiltered view. Someone suggested I explicitly call view.FTSearch inside one of the events (beforePageLoad?) and immediately after do my getAllEntries call, saving the results in viewScope, but I get an "Error while browses Notes view" runtime error when I try to do that. Any pointers? TIA!
EDIT: After studying the xpages lifecycle a bit (which is still a little confusing), I think I can fine-tune my question. This is my first stackoverflow question, so I hope this is okay to do and productive....
As I described, I have a dominoView defined on my xpage. A repeat iterates over the rows of the view, displaying certain fields from the documents. If I define a query in the search property, then the repeat correctly displays the reduced set of documents rather than the complete set. (The query is computed in the search property via SSJS from some variables defined in the viewScope in a combobox's eventHandler.) However, if I try to access the current entries in the view inside of the repeat's rendered section (with SSJS) using myView.getAllEntries (where myView is what's defined as the "value" of the repeat), I am still getting all of the documents, even if a query has been done. It seems like at that point, the view variable has already had its search applied (since the repeat works), so why the differing results? Is there another way to access the view's rows? To complicate this further, this is just a simple experiment that might clarify the problem; as I indicated earlier, I don't actually want to access the view data within the repeat, I want to access it in the rendered or value sections of some comboboxes defined before the repeat in the xpage file.
I hope that makes more sense now....
EDIT #2: I forgot to add that if I manually call FTSearch (or FTSearchSorted) before calling myView.getAllEntries, then I think I can make this work. It just seems unnecessary to have to do that in addition to the view's built-in search.
From what I get you want to iterate over the entries in a view that before has been filtered, i.e. whose resulting entry collection is smaller than the the view itself.
What I don't get (yet) is what you want to do with the result, or what you're axpecting to get from the iteration over your filtered view (you're mentioning some counts to be displayed somewhere else).
Probably a good way is to use the view's .getAllEntriesByKey method which returns a NotesViewEntryCollection object which then can be used for your iteration.
Don't forget to recycle the resulting NotesViewEntry objects; reason for this has been explained several times here at stackoverflow.

CouchDB views - Multiple join... Can it be done?

I have three document types MainCategory, Category, SubCategory... each have a parentid which relates to the id of their parent document.
So I want to set up a view so that I can get a list of SubCategories which sit under the MainCategory (preferably just using a map function)... I haven't found a way to arrange the view so this is possible.
I currently have set up a view which gets the following output -
{"total_rows":16,"offset":0,"rows":[
{"id":"11098","key":["22056",0,"11098"],"value":"MainCat...."},
{"id":"11098","key":["22056",1,"11098"],"value":"Cat...."},
{"id":"33610","key":["22056",2,"null"],"value":"SubCat...."},
{"id":"33989","key":["22056",2,"null"],"value":"SubCat...."},
{"id":"11810","key":["22245",0,"11810"],"value":"MainCat...."},
{"id":"11810","key":["22245",1,"11810"],"value":"Cat...."},
{"id":"33106","key":["22245",2,"null"],"value":"SubCat...."},
{"id":"33321","key":["22245",2,"null"],"value":"SubCat...."},
{"id":"11098","key":["22479",0,"11098"],"value":"MainCat...."},
{"id":"11098","key":["22479",1,"11098"],"value":"Cat...."},
{"id":"11810","key":["22945",0,"11810"],"value":"MainCat...."},
{"id":"11810","key":["22945",1,"11810"],"value":"Cat...."},
{"id":"33123","key":["22945",2,"null"],"value":"SubCat...."},
{"id":"33453","key":["22945",2,"null"],"value":"SubCat...."},
{"id":"33667","key":["22945",2,"null"],"value":"SubCat...."},
{"id":"33987","key":["22945",2,"null"],"value":"SubCat...."}
]}
Which QueryString parameters would I use to get say the rows which have a key that starts with ["22945".... When all I have (at query time) is the id "11810" (at query time I don't have knowledge of the id "22945").
If any of that makes sense.
Thanks
The way you store your categories seems to be suboptimal for the query you try to perform on it.
MongoDB.org has a page on various strategies to implement tree-structures (they should apply to Couch and other doc dbs as well) - you should consider Array of Ancestors, where you always store the full path to your node. This makes updating/moving categories more difficult, but querying is easy and fast.

Resources