I was able to accomplish this in a few steps in SXA 9.3. This approach implements the ISearchService
included with SXA. We're basically extracting code that is used by the SearchController
.
Step 1 : Implement the custom search function. Add this to your IGenerateScribanContextProcessor
.
private delegate IEnumerable<Item> SearchItemsDelegate(Item item, string s, string q = null, string o = null, int p = 10, int e = -1, string g = null, double r = -1);
protected ISearchService SearchService { get; } = ServiceLocator.ServiceProvider.GetService<ISearchService>();
protected ISortingService SortingService { get; } = ServiceLocator.ServiceProvider.GetService<ISortingService>();
public IEnumerable<Item> SearchItemsImpl(Item item, string s, string q = null, string o = null, int p = 10, int e = -1, string g = null, double r = -1)
{
var siteInfo = SiteResolver.GetSiteInfo(item);
var scopesIDs = s?.Split(',', '|').Where(ID.IsID).Select(ID.Parse);
Coordinate center = null;
if (!string.IsNullOrEmpty(g))
{
center = g?.Replace("|", ",");
}
var query = this.SearchService.GetQuery(new SearchQueryModel
{
Coordinates = center,
ItemID = item?.ID,
Query = q,
ScopesIDs = scopesIDs
}, out var indexName);
var sortings = o?.Split('|').TrimAndRemoveEmpty();
query = this.SortingService.Order(query, sortings, center, siteInfo.Name);
if (e > 0)
{
query = query.Skip(e);
}
if (p > 0)
{
query = query.Take(p);
}
return query.Select(i => i.Uri).ToList()
.Select(u => Factory.GetDatabase(u.DatabaseName)
.GetItem(u.ItemID, u.Language, u.Version));
}
Step 2 : Add the function to the global script object.
args.GlobalScriptObject.Import("sc_searchitems", new SearchItemsDelegate(SearchItemsImpl));
Step 3 : Add a scriban rendering variant.
{{
queryid = "{BBC62A76-2207-465B-BA0D-073BE71FD90C}"
fieldname = "Title"
}}
<ul class="items">
{{ for i_searchitem in ( sc_searchitems i_page queryid o: "Title,Ascending" p: 50 ) }}
<li>{{ i_searchitem.Fields[fieldname] }}</li>
{{ end }}
</ul>
Note: This version may have some missing features. If you improve upon feel free to share with me and I'll update this answer.
Update: You may have noticed that at the end of the code where the items are pulled from the search engine that Uri
is selected. In my experience I've found that the SXA search can be made significantly faster by selected just the Uri
from the search engine and then getting items based on that property. A feature request would be for SXA to do the same by default.