Monday, February 22, 2016

Implementing pagination on search in 12c

Pagination on search pages is quite a common requirement and with introduction of WebCenter Sites 12c, it has become even more easier to do so. If you are looking for implementing pagination on search results for 11g, you can check my old post here.

With introduction of new server-side api, its very easy to perform CRUD operation on assets. For searching assets, Searcher helper class provides methods to include various options which is very easier to implement.
Note: For using Searcher, global indexes for the assettype should be enabled.

Following is simple illustration of searching product assets of particular locale (en_US) in FirstSiteII, it can also search on product name, order by date and shows 10 results per page.

package oracle.webcenter.sites.controller
import groovy.json.JsonOutput;
import COM.FutureTense.Interfaces.Utilities;
import com.fatwire.assetapi.data.*
import com.fatwire.assetapi.data.search.impl.Searcher
import com.fatwire.assetapi.data.search.BinaryRelationalOperator;
import com.fatwire.assetapi.data.search.Orders;
import com.fatwire.assetapi.data.search.Filter;
import com.fatwire.assetapi.data.search.SearchHelper;
import com.fatwire.assetapi.data.search.SortDirection;
import com.fatwire.assetapi.data.search.impl.OrderBuilder;
import com.openmarket.xcelerate.asset.*
import com.fatwire.assetapi.fragment.*
/**
* @author: fatwiredev
*
* Implementation of searching Product_C assets in FirstSiteII
* on basis of following:
*
* locale = dimension of asset
* order = ascending/descending on product date (new attribute: FSIIProductDate)
* page = page number
* text = text input from user (new attribute: FSIIProductName)
*
*/
public class ProductSearchController extends BaseController
{
public void searchContent(){
def assetType = "Product_C"
List<Map<String, String>> searchResults = null
def locale = Utilities.goodString(getVariables().get("locale")) ? getVariables().get("locale") : queryParams.locale;
//Order by FSIIProductDate first and then FSIIProductName
Orders order = newOrderChain("FSIIProductDate").thenBy(SortDirection.DESCENDING, "FSIIProductDate", "FSIIProductName").build();
//locale condition
Filter localeFilter = newFilter("locale", BinaryRelationalOperator.EQUALS, locale);
//Get the text from url parameter: text
List<String> searchedTextList = queryParams.text
String searchText = null;
for(String searchedText: searchedTextList){
searchText = searchedText;
}
//Set condition
Filter finalQuery = localeFilter
if(Utilities.goodString(searchText)){
Filter textQuery = newFilter("FSIIProductName", BinaryRelationalOperator.CONTAINS, searchText);
finalQuery = finalQuery.and(textQuery);
}
//Build common search
Searcher searcher = SearchHelper.newFieldSearcherForTypeInSite("FSIIProductName", assetType, "FirstSiteII", finalQuery, order)
// Search & Find total number of results
// and set total results in scope to show something like
// "Showing 1 - 10 results of 54 results"
int numberOfResults = (searcher.search()).size()
models.put("total",numberOfResults)
//Get requested page number from url parameter: page
List pageNumber = null
if(null != queryParams.page) pageNumber = queryParams.page
//Index to start from
int index = pageNumber != null && pageNumber.size()>0 && pageNumber[0] != 1 ? 10*(Integer.valueOf(pageNumber[0]) - 1) + 1 : 1
// Search by setting index and top results
// if page == 1 --> index = 1 and top = 10
// if page == 2 --> index = 11 and top = 20
// and so on.....
searchResults = searcher.startAt(index).top(10*index).search()
//phew... finally fetch data and set in scope to be consumed by JSP using JSTL tag
if(searchResults != null) {
List<Map<String, String>> results = new ArrayList<Map<String,String>>()
Map assetMap = null
for(Map<String, String> map in searchResults)
{
assetMap = newAssetReader()
.forAsset(assetType, Long.parseLong(map.id))
.includeLinks(true)
.includeLinksForBlobs(true)
.selectAll(true)
.read()
results.add(assetMap)
}
if(assetMap != null && !results.empty) {
models.put("results", results)
}
}
}
@Override
@RequiredParams(query="c,cid")
public void doWork(Map models)
{
searchContent();
}
/*
* NOTE:
* queryParams.[QUERY_STRING] --> variable present as query param in url also called as query string
* getVariables().get("[VARIABLE NAME]") --> Variable present in ics scope
* variables.[VARIABLE NAME] === getVariables().get("[VARIABLE NAME]") === ics.GetVar("VARIABLE NAME")
*/
}
Click here to download this sample groovy class.

Need help? Click here.

3 comments:

  1. Many Thanks.. It helps alot :)

    ReplyDelete
  2. How to implement same on 11.1.8

    ReplyDelete
    Replies
    1. http://fatwirecode.blogspot.in/2015/07/implementing-pagination-on-search.html

      Delete