<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Search</title><link>https://community.telligent.com/community/11/w/developer-training/65107/search</link><description /><dc:language>en-US</dc:language><generator>14.0.0.586 14</generator><item><title>Search</title><link>https://community.telligent.com/community/11/w/developer-training/65107/search</link><pubDate>Thu, 09 Jul 2020 18:13:19 GMT</pubDate><guid isPermaLink="false">72a5bf89-2c72-45d4-932c-62a2184b0633</guid><dc:creator>Ramzi Banna</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65107/search#comments</comments><description>Current Revision posted to Developer Training by Ramzi Banna on 07/09/2020 18:13:19&lt;br /&gt;
&lt;p&gt;The [[api-documentation:ISearchableContentType Plugin Type|ISearchableContentType]] interface provides support for making content searchable. When the search index job runs this plugin is used to gather information about your content.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h3&gt;&lt;a id="Why_should_I_make_my_content_searchable" name="Why_should_I_make_my_content_searchable"&gt;&lt;/a&gt;Why should I make my content searchable?&lt;/h3&gt;
&lt;p&gt;Search is a powerful feature in any community. If making your content discoverable then planning on a search strategy is important. Consider what properties are important to index for making your content distinguishable from other content on the search page.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Creating_an_ISearchableContentType_plugin" name="Creating_an_ISearchableContentType_plugin"&gt;&lt;/a&gt;Creating an ISearchableContentType plugin&lt;/h3&gt;
&lt;p&gt;To add support for search you must implement the [[api-documentation:ISearchableContentType Plugin Type|ISearchableContentType]]. It is defined in the &lt;code&gt;Telligent.Evolution.Extensibility.Content.Version1&lt;/code&gt; namespace of &lt;code&gt;Telligent.Evolution.Core.dll&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is important to note that one or more Core Services can be implemented in the same [[api-documentation:IContentType Plugin Type|IContentType]] class.&lt;/p&gt;
&lt;p&gt;Begin by defining a method to flag what content is or is not index by the search provider.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void SetIndexStatus(Guid[] contentIds, bool isIndexed)
{
    LinksData.UpdateStatus(contentIds, isIndexed);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;For the next method it is important to consider what fields will be indexed. You will need to build a list of&amp;nbsp;[[api-documentation:SearchIndexDocument Plugin Supplementary Type|SearchIndexDocuments]] by using the API &lt;code&gt;Apis.Get&amp;lt;ISearchIndexing&amp;gt;().NewDocument()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public IList&amp;lt;SearchIndexDocument&amp;gt; GetContentToIndex()
{
    var docs = new List&amp;lt;SearchIndexDocument&amp;gt;();
    var links = LinksData.ListLinks().Where(link =&amp;gt; !link.IsIndexed);

    foreach (var link in links)
    {
        if (link == null) { continue; }

        var doc = Apis.Get&amp;lt;ISearchIndexing&amp;gt;().NewDocument(link.ContentId, link.ContentTypeId, &amp;quot;linkitem&amp;quot;, link.Url, link.HtmlName(&amp;quot;web&amp;quot;), link.HtmlDescription(&amp;quot;web&amp;quot;));
        doc.AddField(&amp;quot;date&amp;quot;, Apis.Get&amp;lt;ISearchIndexing&amp;gt;().FormatDate(link.CreatedDate));
        docs.Add(doc);
    }

    return docs;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Security trimming is another important feature of the search provider. It determines if a user has permission to view certain content. This will require you to return a list of roles that are allowed to view your content.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public int[] GetViewSecurityRoles(Guid contentId)
{
    var content = LinksData.GetLink(contentId);
    if (content == null) { return new int[] { }; }
    if (content.Application == null) { return new int[] { }; }

    return Apis.Get&amp;lt;IRoles&amp;gt;().Find(&amp;quot;Registered Users&amp;quot;).Select(r =&amp;gt; r.Id.GetValueOrDefault()).ToArray();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;One of the final methods to implement returns the html view for the search result. It is important to return a consistent format but you will have full control over the markup that is returned for your content.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string GetViewHtml(IContent content, Target target)
{
    if (content == null) { return null; }

    var user = Apis.Get&amp;lt;IUsers&amp;gt;().Get(new UsersGetOptions { Id = content.CreatedByUserId });

    var author = String.Format(@&amp;quot;&amp;lt;a href=&amp;quot;&amp;quot;{0}&amp;quot;&amp;quot; class=&amp;quot;&amp;quot;internal-link view-user-profile&amp;quot;&amp;quot;&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;, PublicApi.Html.EncodeAttribute(user.ProfileUrl), PublicApi.Html.Encode(user.DisplayName));
    
    var appLink = content.Application != null
        ? String.Format(@&amp;quot;&amp;lt;a href=&amp;quot;&amp;quot;{0}&amp;quot;&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;, PublicApi.Html.EncodeAttribute(content.Application.Url), content.Application.HtmlName(target.ToString()))
        : String.Empty;
    
    var groupLink = content.Application != null &amp;amp;&amp;amp; content.Application.Container != null
        ? String.Format(@&amp;quot;&amp;lt;a href=&amp;quot;&amp;quot;{0}&amp;quot;&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;, PublicApi.Html.EncodeAttribute(content.Application.Container.Url), content.Application.Container.HtmlName(target.ToString()))
        : String.Empty;

    return String.Format(@&amp;quot;
&amp;lt;div class=&amp;quot;&amp;quot;abbreviated-post-header&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;&amp;quot;abbreviated-post ui-searchresult&amp;quot;&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;&amp;quot;post-metadata&amp;quot;&amp;quot;&amp;gt;
        &amp;lt;ul class=&amp;quot;&amp;quot;property-list&amp;quot;&amp;quot;&amp;gt;
            &amp;lt;li class=&amp;quot;&amp;quot;property-item date&amp;quot;&amp;quot;&amp;gt;{0}&amp;lt;/li&amp;gt;
                &amp;lt;li class=&amp;quot;&amp;quot;property-item author&amp;quot;&amp;quot;&amp;gt;
                    &amp;lt;span class=&amp;quot;&amp;quot;user-name&amp;quot;&amp;quot;&amp;gt;{1}&amp;lt;/span&amp;gt;
                &amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;
                &amp;lt;ul class=&amp;quot;&amp;quot;details&amp;quot;&amp;quot;&amp;gt;
                    &amp;lt;li class=&amp;quot;&amp;quot;property-item type&amp;quot;&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;
                &amp;lt;/ul&amp;gt;
            &amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;h4 class=&amp;quot;&amp;quot;post-name&amp;quot;&amp;quot;&amp;gt;
        &amp;lt;a class=&amp;quot;&amp;quot;internal-link view-post&amp;quot;&amp;quot; title=&amp;quot;&amp;quot;{3}&amp;quot;&amp;quot; href=&amp;quot;&amp;quot;{4}&amp;quot;&amp;quot;&amp;gt;
            {2}
        &amp;lt;/a&amp;gt;
    &amp;lt;/h4&amp;gt;
    &amp;lt;div class=&amp;quot;&amp;quot;post-summary&amp;quot;&amp;quot;&amp;gt;{5}&amp;lt;/div&amp;gt;
    &amp;lt;div class=&amp;quot;&amp;quot;post-application&amp;quot;&amp;quot;&amp;gt;
        {6}
        {7}
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;&amp;quot;abbreviated-post-footer&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;,
    Apis.Get&amp;lt;ILanguage&amp;gt;().FormatDate(content.CreatedDate),
    author,
    content.HtmlName(&amp;quot;web&amp;quot;),
    content.HtmlName(&amp;quot;web&amp;quot;),
    PublicApi.Html.EncodeAttribute(content.Url),
    content.HtmlDescription(&amp;quot;web&amp;quot;),
    appLink,
    groupLink);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is the full sample.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1374_2E00_LinkItemContentType_2E00_cs"&gt;community.telligent.com/.../1374_2E00_LinkItemContentType_2E00_cs&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: index, plugin, search&lt;/div&gt;
</description></item><item><title>Search</title><link>https://community.telligent.com/community/11/w/developer-training/65107/search/revision/1</link><pubDate>Thu, 13 Jun 2019 19:28:36 GMT</pubDate><guid isPermaLink="false">72a5bf89-2c72-45d4-932c-62a2184b0633</guid><dc:creator>Ben Tiedt</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65107/search#comments</comments><description>Revision 1 posted to Developer Training by Ben Tiedt on 06/13/2019 19:28:36&lt;br /&gt;
&lt;p&gt;The [[api-documentation:ISearchableContentType Plugin Type|ISearchableContentType]] interface provides support for making content searchable. When the search index job runs this plugin is used to gather information about your content.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h3&gt;&lt;a id="Why_should_I_make_my_content_searchable" name="Why_should_I_make_my_content_searchable"&gt;&lt;/a&gt;Why should I make my content searchable?&lt;/h3&gt;
&lt;p&gt;Search is a powerful feature in any community. If making your content discoverable then planning on a search strategy is important. Consider what properties are important to index for making your content distinguishable from other content on the search page.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Creating_an_ISearchableContentType_plugin" name="Creating_an_ISearchableContentType_plugin"&gt;&lt;/a&gt;Creating an ISearchableContentType plugin&lt;/h3&gt;
&lt;p&gt;To add support for search you must implement the [[api-documentation:ISearchableContentType Plugin Type|ISearchableContentType]]. It is defined in the &lt;code&gt;Telligent.Evolution.Extensibility.Content.Version1&lt;/code&gt; namespace of &lt;code&gt;Telligent.Evolution.Core.dll&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is important to note that one or more Core Services can be implemented in the same [[api-documentation:IContentType Plugin Type|IContentType]] class.&lt;/p&gt;
&lt;p&gt;Begin by defining a method to flag what content is or is not index by the search provider.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void SetIndexStatus(Guid[] contentIds, bool isIndexed)
{
    LinksData.UpdateStatus(contentIds, isIndexed);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;For the next method it is important to consider what fields will be indexed. You will need to build a list of&amp;nbsp;[[api-documentation:SearchIndexDocument Plugin Supplementary Type|SearchIndexDocuments]] by using the API &lt;code&gt;Apis.Get&amp;lt;ISearchIndexing&amp;gt;().NewDocument()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public IList&amp;lt;SearchIndexDocument&amp;gt; GetContentToIndex()
{
    var docs = new List&amp;lt;SearchIndexDocument&amp;gt;();
    var links = LinksData.ListLinks().Where(link =&amp;gt; !link.IsIndexed);

    foreach (var link in links)
    {
        if (link == null) { continue; }

        var doc = Apis.Get&amp;lt;ISearchIndexing&amp;gt;().NewDocument(link.ContentId, link.ContentTypeId, &amp;quot;linkitem&amp;quot;, link.Url, link.HtmlName(&amp;quot;web&amp;quot;), link.HtmlDescription(&amp;quot;web&amp;quot;));
        doc.AddField(&amp;quot;date&amp;quot;, Apis.Get&amp;lt;ISearchIndexing&amp;gt;().FormatDate(link.CreatedDate));
        docs.Add(doc);
    }

    return docs;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Security trimming is another important feature of the search provider. It determines if a user has permission to view certain content. This will require you to return a list of roles that are allowed to view your content.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public int[] GetViewSecurityRoles(Guid contentId)
{
    var content = LinksData.GetLink(contentId);
    if (content == null) { return new int[] { }; }
    if (content.Application == null) { return new int[] { }; }

    return Apis.Get&amp;lt;IRoles&amp;gt;().Find(&amp;quot;Registered Users&amp;quot;).Select(r =&amp;gt; r.Id.GetValueOrDefault()).ToArray();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;One of the final methods to implement returns the html view for the search result. It is important to return a consistent format but you will have full control over the markup that is returned for your content.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string GetViewHtml(IContent content, Target target)
{
    if (content == null) { return null; }

    var user = Apis.Get&amp;lt;IUsers&amp;gt;().Get(new UsersGetOptions { Id = content.CreatedByUserId });

    var author = String.Format(@&amp;quot;&amp;lt;a href=&amp;quot;&amp;quot;{0}&amp;quot;&amp;quot; class=&amp;quot;&amp;quot;internal-link view-user-profile&amp;quot;&amp;quot;&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;, PublicApi.Html.EncodeAttribute(user.ProfileUrl), PublicApi.Html.Encode(user.DisplayName));
    
    var appLink = content.Application != null
        ? String.Format(@&amp;quot;&amp;lt;a href=&amp;quot;&amp;quot;{0}&amp;quot;&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;, PublicApi.Html.EncodeAttribute(content.Application.Url), content.Application.HtmlName(target.ToString()))
        : String.Empty;
    
    var groupLink = content.Application != null &amp;amp;&amp;amp; content.Application.Container != null
        ? String.Format(@&amp;quot;&amp;lt;a href=&amp;quot;&amp;quot;{0}&amp;quot;&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;, PublicApi.Html.EncodeAttribute(content.Application.Container.Url), content.Application.Container.HtmlName(target.ToString()))
        : String.Empty;

    return String.Format(@&amp;quot;
&amp;lt;div class=&amp;quot;&amp;quot;abbreviated-post-header&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;&amp;quot;abbreviated-post ui-searchresult&amp;quot;&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;&amp;quot;post-metadata&amp;quot;&amp;quot;&amp;gt;
        &amp;lt;ul class=&amp;quot;&amp;quot;property-list&amp;quot;&amp;quot;&amp;gt;
            &amp;lt;li class=&amp;quot;&amp;quot;property-item date&amp;quot;&amp;quot;&amp;gt;{0}&amp;lt;/li&amp;gt;
                &amp;lt;li class=&amp;quot;&amp;quot;property-item author&amp;quot;&amp;quot;&amp;gt;
                    &amp;lt;span class=&amp;quot;&amp;quot;user-name&amp;quot;&amp;quot;&amp;gt;{1}&amp;lt;/span&amp;gt;
                &amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;
                &amp;lt;ul class=&amp;quot;&amp;quot;details&amp;quot;&amp;quot;&amp;gt;
                    &amp;lt;li class=&amp;quot;&amp;quot;property-item type&amp;quot;&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;
                &amp;lt;/ul&amp;gt;
            &amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;h4 class=&amp;quot;&amp;quot;post-name&amp;quot;&amp;quot;&amp;gt;
        &amp;lt;a class=&amp;quot;&amp;quot;internal-link view-post&amp;quot;&amp;quot; title=&amp;quot;&amp;quot;{3}&amp;quot;&amp;quot; href=&amp;quot;&amp;quot;{4}&amp;quot;&amp;quot;&amp;gt;
            {2}
        &amp;lt;/a&amp;gt;
    &amp;lt;/h4&amp;gt;
    &amp;lt;div class=&amp;quot;&amp;quot;post-summary&amp;quot;&amp;quot;&amp;gt;{5}&amp;lt;/div&amp;gt;
    &amp;lt;div class=&amp;quot;&amp;quot;post-application&amp;quot;&amp;quot;&amp;gt;
        {6}
        {7}
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;&amp;quot;abbreviated-post-footer&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;,
    Apis.Get&amp;lt;ILanguage&amp;gt;().FormatDate(content.CreatedDate),
    author,
    content.HtmlName(&amp;quot;web&amp;quot;),
    content.HtmlName(&amp;quot;web&amp;quot;),
    PublicApi.Html.EncodeAttribute(content.Url),
    content.HtmlDescription(&amp;quot;web&amp;quot;),
    appLink,
    groupLink);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is the full sample.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1374_2E00_LinkItemContentType_2E00_cs"&gt;community.telligent.com/.../1374_2E00_LinkItemContentType_2E00_cs&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item></channel></rss>