Take the community feedback survey now.
Take the community feedback survey now.
Hi,
I have created a Gist with the code I have written and using for paging (works for any IEnumerable<T>) that you can take a look at. You can find it here. To use this code you can modify your search page view model by changing the type of the Hits property to IPagedEnumerable<SearchHit>:
public IPagedEnumerable<SearchHit> Hits { get; set; }
Next, modify your action so it handles a page querystring parameter:
public ViewResult Index(SearchPage currentPage, string q, int page = 1)
And in your action where you create an instance of the view model you set the Hits property like this:
int pageSize = 10;
var hits = Search(q.Trim(), ContentReference.StartPage, ControllerContext.HttpContext, currentPage.LanguageID).ToList();
model.Hits = new PagedList<SearchPageModel.SearchHit>(HttpContext, hits, page, pageSize)
{
QueryParamName = "page"
};
Finally in the view, somewhere below or above the search results, you render the paging partial that you can find in the Gist:
@{ Html.RenderPartial("_Paging", Model.Hits); }
I would also modify the SearchService class in Alloy so it handles paging, so you only get back the results for the current page. In the implementation I have (maybe it's an old version of Alloy) it just gets the 40 first hits. This Search method should be changed from:
public virtual SearchResults Search(string searchText, PageReference rootPage, HttpContextBase context, string languageBranch,
string[] fileDirectories, int maxResults)
{
var query = CreateQuery(searchText, rootPage, context, languageBranch, fileDirectories);
return _searchHandler.GetSearchResults(query, 1, maxResults);
}
To:
public virtual SearchResults Search(string searchText, PageReference rootPage, HttpContextBase context, string languageBranch,
string[] fileDirectories, int page, int pageSize)
{
var query = CreateQuery(searchText, rootPage, context, languageBranch, fileDirectories);
return _searchHandler.GetSearchResults(query, page, pageSize);
}
Next you should modify the Search method in the SearchPage controller:
private IEnumerable<SearchPageModel.SearchHit> Search(string searchText, PageReference rootPage, HttpContextBase context, string languageBranch, int page, int pageSize, out int numberOfHits)
{
var searchResults = _searchService.Search(searchText, rootPage, context, languageBranch, _fileDirectories, page, pageSize);
numberOfHits = searchResults.TotalHits;
return searchResults.IndexResponseItems.SelectMany(CreateHitModel);
}
And finally, use this code in the Index action:
int numberOfHits;
int pageSize = 10;
var hits = Search(q.Trim(), ContentReference.StartPage, ControllerContext.HttpContext, currentPage.LanguageID, page, pageSize, out numberOfHits).ToList();
model.Hits = new PagedList<SearchPageModel.SearchHit>(HttpContext, hits, numberOfHits, page, pageSize)
{
QueryParamName = "page"
};
model.NumberOfHits = numberOfHits;
When modifying the Search Service I have a different version (IEnumerable<ContentReference> searchRoots instead of PageReference rootPage).
If I modifiy it I will also need to modify the CreateQuery method.
These are my versions.
Search
public virtual SearchResults Search(string searchText, IEnumerable<ContentReference> searchRoots, HttpContextBase context, string languageBranch, int maxResults)
{
var query = CreateQuery(searchText, searchRoots, context, languageBranch);
return _searchHandler.GetSearchResults(query, 1, maxResults);
}
CreateQuery
private IQueryExpression CreateQuery(string searchText, IEnumerable<ContentReference> searchRoots, HttpContextBase context, string languageBranch)
{
//Main query which groups other queries. Each query added
//must match in order for a page or file to be returned.
var query = new GroupQuery(LuceneOperator.AND);
//Add free text query to the main query
query.QueryExpressions.Add(new FieldQuery(searchText));
//Search for pages using the provided language
var pageTypeQuery = new GroupQuery(LuceneOperator.AND);
pageTypeQuery.QueryExpressions.Add(new ContentQuery<PageData>());
pageTypeQuery.QueryExpressions.Add(new FieldQuery(languageBranch, Field.Culture));
//Search for media without languages
var contentTypeQuery = new GroupQuery(LuceneOperator.OR);
contentTypeQuery.QueryExpressions.Add(new ContentQuery<MediaData>());
contentTypeQuery.QueryExpressions.Add(pageTypeQuery);
query.QueryExpressions.Add(contentTypeQuery);
//Create and add query which groups type conditions using OR
var typeQueries = new GroupQuery(LuceneOperator.OR);
query.QueryExpressions.Add(typeQueries);
foreach (var root in searchRoots)
{
var contentRootQuery = new VirtualPathQuery();
contentRootQuery.AddContentNodes(root, _contentLoader);
typeQueries.QueryExpressions.Add(contentRootQuery);
}
var accessRightsQuery = new AccessControlListQuery();
accessRightsQuery.AddAclForUser(PrincipalInfo.Current, context);
query.QueryExpressions.Add(accessRightsQuery);
return query;
}
It also says that _fileDirectories doesn't exist in the SearchPageController.
Hi everyone!
I'm trying to sort the search results of the Alloy example MVC in pages but I don't know how to start doing it and I need someone who guides me a little bit in my way to do it.
I'm not using EPiServer Find, is essential to use it to make this work?
Thanks =)