Do you want to implement Lucene search in Sitecore and
unable to get where to start exactly? Fuck all those theory on internet and
refer this straight forward guide.
Rename “\Website\App_Config\IncludeSitecore.ContentSearch.Lucene.Index.Master.config”
to “IncludeSitecore.ContentSearch.Lucene.Index.Surendra.config”
Open and do the following highlighted config changes.
Basically add your template IDs which do you want to show as a search result
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<configuration type="Sitecore.ContentSearch.ContentSearchConfiguration,
Sitecore.ContentSearch">
<indexes hint="list:AddIndex">
<index id="Surendra" type="Sitecore.ContentSearch.LuceneProvider.LuceneIndex,
Sitecore.ContentSearch.LuceneProvider">
<param desc="name">$(id)</param>
<param desc="folder">$(id)</param>
<!-- This initializes index property store. Id has to be set
to the index id -->
<param desc="propertyStore" ref="contentSearch/indexConfigurations/databasePropertyStore" param1="$(id)" />
<configuration ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration">
<include hint="list:IncludeTemplate">
<Template1>{11111111-2222-3333-4444-123456789123}</Template1>
<Template2>{11111111-2222-3333-4444-123456789124}</Template2>
<Template3>{11111111-2222-3333-4444-123456789125}</Template3>
<Template4>{11111111-2222-3333-4444-123456789126}</Template4>
<Template5>{11111111-2222-3333-4444-123456789127}</Template5>
</include>
<IndexAllFields>true</IndexAllFields>
</configuration>
<strategies hint="list:AddStrategy">
<!-- NOTE: order of these is controls the execution order -->
<strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/onPublishEndAsync" />
</strategies>
<!--<commitPolicyExecutor
type="Sitecore.ContentSearch.CommitPolicyExecutor,
Sitecore.ContentSearch">
<policies
hint="list:AddCommitPolicy">
<policy
type="Sitecore.ContentSearch.TimeIntervalCommitPolicy, Sitecore.ContentSearch"
/>
</policies>
</commitPolicyExecutor>-->
<locations hint="list:AddCrawler">
<crawler type="Sitecore.ContentSearch.SitecoreItemCrawler,
Sitecore.ContentSearch">
<Database>master</Database>
<Root>/sitecore/content/Surendra/Homepage</Root>
</crawler>
</locations>
<!--
<shardingStrategy
type="Sitecore.ContentSearch.LuceneProvider.Sharding.LucenePartitionShardingStrategy,
Sitecore.ContentSearch.LuceneProvider">
<param
desc="shardDistribution">4</param>
</shardingStrategy>
-->
<!--
<shardFolders
hint="raw:AddShardFolderPath">
<shard shardName="shard1"
shardRootFolderPath="c:\Data\Indexes" />
<shard
shardName="shard2" shardRootFolderPath="c:\Data\Indexes"
/>
<shard
shardName="shard3" shardRootFolderPath="c:\Data\Indexes"
/>
</shardFolders>
-->
</index>
</indexes>
</configuration>
</contentSearch>
</sitecore>
</configuration>
Open Sitecore Desktop version -> Control Panel ->
Indexing – Indexing Manager -> Checked only “Surendra” Instance -> Next -> Finish [There must be some units processed at this stage.]
Goto IIS and recycle application pool of your site.
Create Search content item and set Search control
layout with this content item.
Add below HTML and C# code in this Search page
<asp:TextBox runat="server" ID="txtsearch" ></asp:TextBox>
<asp:Button runat="server" ID="btnSearch" Text="Search" OnClick="btnSearch_Click" CssClass="searchbtn" />
<ul>
<asp:Repeater ID="rptEvents" runat="server">
<ItemTemplate>
<asp:HyperLink NavigateUrl="<%# Sitecore.Links.LinkManager.GetItemUrl((Item)Container.DataItem) %>" runat="server">
<li>
<strong>
Title
Write your
HTML code here
</strong>
</li>
</asp:HyperLink>
</ItemTemplate>
</asp:Repeater>
</ul>
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Analysis;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.SearchTypes;
using Sitecore.Data.Items;
/// <summary>
/// Search Page
/// </summary>
public partial class Search : System.Web.UI.UserControl
{
#region
Properties
public string LeftPartClass { get; set; }
private int RowCount
{
get
{
int result = 0;
if (ViewState["RowCount"] != null)
{
result = (int)ViewState["RowCount"];
}
return result;
}
set
{
ViewState["RowCount"] = value;
}
}
#endregion
#region
Page Load
/// <summary>
/// Page Load
/// </summary>
/// <param
name="sender"></param>
/// <param
name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
LeftPartClass = "Show";
if (!IsPostBack)
{
RowCount = 0;
if (Request.QueryString != null && Request.QueryString.Count > 0 && !string.IsNullOrEmpty(Request.QueryString["q"]))
{
Session["q"] =
Request.QueryString["q"].Trim();
}
SearchContent(Session["q"], 10,
0);
}
else
{
plcPagingTop.Controls.Clear();
plcPagingBottom.Controls.Clear();
CreatePagingControl();
}
}
#endregion
#region
ASP.NET Event
/// <summary>
/// Search button
/// </summary>
/// <param
name="sender"></param>
/// <param
name="e"></param>
protected void btnSearch_Click(object sender, EventArgs e)
{
Session["q"] =
txtsearch.Text.Trim();
Response.Redirect(Request.UrlReferrer.AbsolutePath);
}
#endregion
#region
Paging Section
/// <summary>
/// Create Page number
/// </summary>
private void CreatePagingControl()
{
//Get
total pages
int totalPage = (RowCount / 10) + 1;
//Check
initiliase boundry coditions
if (totalPage == 1)
{
totalPage = 0;
}
//Check
last boundry coditions
if(RowCount % 10 == 0)
{
totalPage = RowCount / 10;
}
GeneratePageNumber(totalPage, "Top",
plcPagingTop);
GeneratePageNumber(totalPage, "Bottom",
plcPagingBottom);
}
/// <summary>
/// Generate page number for all pager
/// </summary>
/// <param
name="totalPage"></param>
/// <param
name="pagerLocation"></param>
/// <param
name="placeHolder"></param>
private void GeneratePageNumber(int totalPage, string pagerLocation, PlaceHolder placeHolder)
{
for (int iCounter = 0; iCounter < totalPage; iCounter++)
{
LinkButton lnk = new LinkButton();
lnk.Click += new EventHandler(lbl_Click);
lnk.ID = "lnkPage" +
pagerLocation + (iCounter + 1).ToString();
lnk.Text = (iCounter +
1).ToString();
placeHolder.Controls.Add(lnk);
Label spacer = new Label();
spacer.ID = "lblSpace" +
pagerLocation +(iCounter + 1).ToString();
spacer.Text = " ";
placeHolder.Controls.Add(spacer);
}
}
/// <summary>
/// Show selected page number search
/// </summary>
/// <param
name="sender"></param>
/// <param
name="e"></param>
void lbl_Click(object sender, EventArgs e)
{
LinkButton lnk = sender as LinkButton;
int currentPage = int.Parse(lnk.Text);
hdnPageNum.Value =
currentPage.ToString();
int take = currentPage * 10;
int skip = currentPage == 1 ? 0 : take - 10;
SearchContent(Session["q"], take,
skip);
}
#endregion
#region Search
Block
/// <summary>
/// get search content and render accordingly
/// </summary>
/// <param
name="input"></param>
private void SearchContent(string input, int take, int skip)
{
if (string.IsNullOrEmpty(input))
{
if (Request.QueryString != null && Request.QueryString.Count > 0 && !string.IsNullOrEmpty(Request.QueryString["q"]))
{
Session["q"] =
Request.QueryString["q"].Trim();
input = Request.QueryString["q"].Trim();
}
else
{
LeftPartClass = "Hide";
return;
}
}
ltMessage.Text = string.Format("0 results found for
<strong>\"{0}\"</strong>", input);
string textToSearch = input;
List<string> terms = TokenizeByStandardAnalyzer(textToSearch);
ISearchIndex index = Sitecore.ContentSearch.ContentSearchManager.GetIndex("Surendra");
using (IProviderSearchContext context = index.CreateSearchContext())
{
var expression = BuildSearchExpression(terms);
var query = context.GetQueryable<SearchResultItem>().Where(expression);
List<SearchResultItem> results = query.ToList();
if (results.Count > 0)
{
var searchItemList =
results.Select(x => Sitecore.Context.Database.GetItem(x.ItemId)).Select(x => new
{
DisplayName =
x.DisplayName,
ItemURL =
Sitecore.Links.LinkManager.GetItemUrl(x)
}).Distinct().OrderBy(x=> x.DisplayName).ToList();
int totalRecords =
searchItemList.Count();
var pagingRecords = from p in searchItemList.ToList()
.Take(take)
.Skip(skip)
select p;
PagedDataSource page = new PagedDataSource();
page.AllowCustomPaging = true;
page.AllowPaging = true;
page.DataSource =
pagingRecords;
page.PageSize = 10;
rptEvents.DataSource =
page;
rptEvents.DataBind();
if (!IsPostBack)
{
RowCount =
totalRecords;
CreatePagingControl();
}
int toRecords = (totalRecords < take) ? totalRecords :
take;
ltMessage.Text = string.Format("<strong>{0}-{1}</strong> of about
<strong>{2}</strong> results found for
<strong>\"{3}\"</strong>",
skip + 1, toRecords,
totalRecords, input);
}
}
}
/// <summary>
/// Builds a search Expression for querying the search index
/// </summary>
/// <param
name="terms">IEnumerable List of search
terms</param>
/// <returns></returns>
System.Linq.Expressions.Expression<Func<Sitecore.ContentSearch.SearchTypes.SearchResultItem, bool>>
BuildSearchExpression(IEnumerable<string> terms)
{
var expression = Sitecore.ContentSearch.Linq.Utilities.PredicateBuilder.False<SearchResultItem>();
return terms.Aggregate(expression, (current, term) =>
Sitecore.ContentSearch.Linq.Utilities.PredicateBuilder.Or(current, item => item.Content.Contains(term) ||
item.Name.Contains(term)));
}
/// <summary>
/// Tokenizes the search term string in order to allow multi
term search
/// </summary>
/// <param
name="fieldValue">Search Field Value</param>
/// <returns></returns>
List<string> TokenizeByStandardAnalyzer(string fieldValue)
{
var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
TokenStream stream = analyzer.TokenStream("dummy", new System.IO.StringReader(fieldValue));
var attribute =
stream.AddAttribute<Lucene.Net.Analysis.Tokenattributes.ITermAttribute>();
var list = new List<string>();
while (stream.IncrementToken())
{
string term = attribute.Term;
list.Add(term);
}
stream.End();
return list;
}
#endregion
}
Please leave your comments or share
this tip if it’s useful for you.
Very Nice 5/5
ReplyDeleteDear sir,
ReplyDeletePlease also post step by step guide to implement SOLR search and Path analyzer
Grateful for sharring this
ReplyDelete