<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Search Guys</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/searchguys/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/searchguys/feed.xml</link>
    <description>Everything search, including product commentary and guidance, search strategies and general technical guidance</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:50:10 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Bring Office 365 Video to Sites with Search</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/bring-office-365-video-to-sites-with-search</link>
      <pubDate>Wed, 16 Dec 2015 14:27:28 GMT</pubDate>
      <dc:creator><![CDATA[pjsummersjr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2015/12/16/bring-office-365-video-to-sites-with-search/</guid>
      <description><![CDATA[We’re getting back to our search roots with this blog post! Recently, as part of a customer...]]></description>
      <content:encoded><![CDATA[<p>We’re getting back to our search roots with this blog post!</p> <p>Recently, as part of a customer proof-of-concept, I configured <a href="https://msdn.microsoft.com/en-us/library/office/jj163789.aspx" target="_blank">the content by search web part</a> in a SharePoint Online publishing site to consume and display content from <a href="https://blogs.office.com/2014/11/18/introducing-office-365-video/" target="_blank">Office 365 Video</a>. </p> <p>Office Video is a really cool video platform available in Office 365 that allows users to publish videos, organize them within channels and share them across an organization. To get the most out of that service, it is important for users to be able to consume videos from outside that portal. In July (2015), the product team started rolling out the ability to embed Office 365 Video outside of the portal. This means that we can use that content to provide richer experiences in other SharePoint (and beyond) applications, including intranet portals, team sites, etc.</p> <p>Naturally, I immediately started thinking about how I could surface videos through search and then use the video embed to display them on a SharePoint site page. The content by search web part is a natural fit here because I can provide a dynamic query and also customize the display of the results.</p> <p>It is worth noting that Office 365 Video has <a href="https://msdn.microsoft.com/en-us/office/office365/api/video-rest-operations" target="_blank">its own API</a> but this does not provide a search capability.</p> <h2>Configure CBS Query</h2> <p>The first step was to define the query. For that, I had to inspect some of the Office Video items in search results so I did some targeted queries using the <a href="http://sp2013searchtool.codeplex.com/" target="_blank">SharePoint Search Query Tool</a>. In my environment, I discovered that SharePoint online was classifying these videos as contentclass: sts_listitem_851. I also discovered the pattern for the path to the various site collections that represent the channels in Office Video: <a href="http://tenantname.sharepoint.com/portals/channel-name">http://<em>tenantname</em>.sharepoint.com/portals/<em>channel-name</em></a></p> <p>Ultimately, my query in the CBS looked like the following:</p> <p><font face="Courier New">contentclass: sts_listitem_851 path:{\Site.Url\”&quot;}/../../portals/Executive-Briefing</font></p> <p>where “Executive-Briefing” was the name of my channel. I could have removed “/Executive-Briefing” to search across all videos across the service.</p> <h2></h2> <h2>Configure Display Template Managed Properties</h2> <p>In addition to the standard properties I need to display, like title and description, I also wanted to grab some media-specific properties as well as a few properties that would allow me to dynamically build the embed link. Below is a mapping of logical property to the property name in search:</p> <ul> <li><strong>Video Id: UniqueId</strong>  </li><li><strong>Site Id (channel id): SiteId</strong>  </li><li><strong>Thumbnail Url: PictureThumbnailUrl</strong>  </li><li><strong>Video duration: MediaDuration</strong></li></ul> <h2></h2> <h2></h2> <h2>&nbsp;</h2> <h2>Build Video Elements of Display Template</h2> <p>With the right query and the right properties, I composed my display template so each video result had the title, thumbnail and video duration. Using the <a href="http://foundation.zurb.com/" target="_blank">Foundations Responsive Framework</a>, I created modal popups that actually played the video.</p> <p>Because I didn’t want to make a call to the actual <a href="https://msdn.microsoft.com/en-us/office/office365/api/video-rest-operations#Embedavideoinanotherpage" target="_blank">video API to get the embed code</a>, I built the embed code dynamically:</p> <p><font face="Courier New">var videoEmbedUrl = “portals/hub/_layouts/15/VideoEmbedHost.aspx?chId=” + SiteId+ “&amp;vidId=” + UniqueId + “&amp;width=640&amp;height=360&amp;autoPlay=false&amp;showInfo=true”</font></p> <p>Keep in mind, the format of the embed URL is not officially documented so it could change. Ideally, the Office Video team would include this as one of the properties returned in search.</p> <h2>Other Ideas…</h2> <ul> <li>Consider combining the above search with <a href="https://msdn.microsoft.com/en-us/office/office365/howto/query-Office-graph-using-gql-with-search-rest-api" target="_blank">Graph Query Language</a> to leverage the power of the Office Graph to return the most relevant video to the specific user</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>On-Going Management of Your Master Pages in SharePoint Online</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/on-going-management-of-your-master-pages-in-sharepoint-online</link>
      <pubDate>Tue, 01 Dec 2015 08:08:00 GMT</pubDate>
      <dc:creator><![CDATA[pjsummersjr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2015/12/01/on-going-management-of-your-master-pages-in-sharepoint-online/</guid>
      <description><![CDATA[Updated (12/4/2015): Correction around how default master pages are handled in the service. Thank...]]></description>
      <content:encoded><![CDATA[<p><span style="font-family:Calibri;font-size:medium;"><strong>Updated (12/4/2015):</strong> Correction around how default master pages are handled in the service. Thank you to <a href="https://twitter.com/officedevpnp">@officedevpnp</a> for calling it out.<strong>&nbsp;</strong><br /></span></p>
<p><span style="font-family:Calibri;font-size:medium;">&nbsp;</span></p>
<p><span style="font-family:Calibri;font-size:medium;">Another off-topic post but one that serves as an addendum to <a href="/b/searchguys/archive/2015/05/28/updating-your-sharepoint-master-page-in-sharepoint-online.aspx">my previous post</a>. Customers continue to wrestle with this and it is something the </span><a href="http://dev.office.com/patterns-and-practices"><span style="color:#0563c1;font-family:Calibri;font-size:medium;">Office PnP</span></a><span style="font-family:Calibri;font-size:medium;"> team tends to address theoretically but not practically so I wanted to provide some more practical guidance. </span></p>
<p><span style="font-family:Calibri;font-size:medium;">As a matter of fact, just recently the PnP team posted </span><a href="http://dev.office.com/blogs/branding-sharepoint-using-add-in-model-techniques"><span style="color:#0563c1;font-family:Calibri;font-size:medium;">this video</span></a><span style="font-family:Calibri;font-size:medium;"> about how to apply branding <i>without </i>customizing the SharePoint Online master page and it also provides a lot of guidance about when it is appropriate to customize your master page in SharePoint Online. One point they made which I found particularly noteworthy is that the guidance about when to customize a master page has not changed that dramatically. Microsoft has always encouraged companies to create custom master pages only when it made sense and they had identified requirements that dictated the need. The main reason for that is upgrades. Anytime you had to upgrade SharePoint on-premises, you had to go through a remediation process with the master pages as well as any other customizations. It&rsquo;s the same with SharePoint Online. The difference with SharePoint Online, however, is that the upgrades are happening <i>all the time</i>. That&rsquo;s not to say the master page is changing every time there is an update to the SharePoint Online service but there could be and that&rsquo;s what this blog post is about. </span></p>
<p><a href="/b/searchguys/archive/2015/05/28/updating-your-sharepoint-master-page-in-sharepoint-online.aspx"><span style="color:#0563c1;font-family:Calibri;font-size:medium;">My previous post</span></a><span style="font-family:Calibri;font-size:medium;"> was more tactical as to the particulars of doing an isolated comparison and roll out of those changes. <b>This blog post is about how we manage the on-going process of checking for updates in the service and applying those updates to our custom master page. </b>Below are the key components to this process.</span></p>
<h2><span style="font-family:Calibri;">Capture current state </span></h2>
<p><span style="font-family:Calibri;font-size:medium;">The first thing you need to do is download the default master pages available in SharePoint Online. At the time of this writing, that includes <i>oslo.master</i> and <i>seattle.master. </i>Add these files to your favorite source control repository. </span></p>
<p><span style="font-family:Calibri;font-size:medium;">&nbsp;</span></p>
<h2><span style="font-family:Calibri;">Create your custom page</span></h2>
<p><span style="font-family:Calibri;font-size:medium;">Of course, this article is moot unless you actually create your custom master page. Using one of the defaults as a baseline or using a bare bones master page, create your custom master page but do not overwrite the existing ones. Make sure you give your custom master page a unique name (e.g. contoso.master). If you simply overwrite the out-of-the-box master, <span style="text-decoration:line-through;">your changes will/could get <i>overwritten</i> by O365</span> you will have no way of determining what has changed because your the master page will now be &quot;<a href="http://www.etechplanet.com/blog/ghosted-and-unghosted-pages-in-sharepoint.aspx">unghosted</a>&quot; and will not take updates from the service.&nbsp;Once you&#39;ve created your custom master page, assign <span>it</span> as the master page for your site collection.</span></p>
<p><span style="font-family:Calibri;font-size:medium;">&nbsp;</span></p>
<h2><span style="font-family:Calibri;">On-Going Master Page Evaluation</span></h2>
<p><span style="font-family:Calibri;font-size:medium;">Go through the following steps on a periodic basis. I would suggest quarterly at least, but monthly might be more logical depending on the level of customization and adoption.</span></p>
<ul>
<li><span style="font-size:medium;">Download a copy of oslo.master and seattle.master from your site collection in SharePoint Online. This will be the latest deployed to your tenant in Office 365.</span></li>
<li><span style="font-size:medium;">Update it in your source code repo as a new version</span></li>
<li><span style="font-size:medium;">Compare your new version with the previous version using your favorite diff tool. I use Visual Studio Online for source control so I am able to do a diff of different file versions directly within the browser console of the tool. My previous post talked about WinDiff and either of these as well as many others could work just as well Note any of the changes to the out-of-box master page since the last version</span></li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/master-page-diff.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78/master_2D00_page_2D00_diff.png"><img alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/master-page-diff.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78/master_2D00_page_2D00_diff.png" border="0" /></a><span style="font-size:medium;"><br /></span></p>
<p style="margin-left:60px;"><span style="font-size:medium;"><i>The example above is not really what I had to deal with.&nbsp; In actuality, once I wrapped my mind around the elements of the master page, I think I made <span style="text-decoration:underline;">less than 10 line changes</span> (excluding comments) to update my master page to reflect changes in the service <span style="text-decoration:underline;">over a 2-year period</span></i></span></p>
<ul>
<li><span style="font-size:medium;">Determine if those changes impact your custom master page</span></li>
<li><span style="font-size:medium;">If those changes do impact your custom master page, update your master page accordingly</span></li>
</ul>
<h4><br /><span style="font-family:Calibri;font-size:medium;"> Notes:</span></h4>
<ul>
<li><span style="font-size:medium;">As mentioned above, master page changes from the service can impact your pages primarily in two ways:</span></li>
</ul>
<ol>
<li style="list-style-type:none;"><ol>
<li>
<p><span style="font-size:medium;">A feature might get added to the suite nav or some other global element of the default master page that your site won&rsquo;t see. With our portal, it was the new app launcher. When that rolled out, we were stuck on the old horizontal menu.</span></p>
</li>
<li>
<p><span style="font-size:medium;">The default master pages might add code components (JavaScript or CSS includes) that are contingencies for other existing scripts. The result might be broken features on your master page without any clear idea as to why they&rsquo;re broken.</span></p>
</li>
</ol></li>
</ol>
<ul>
<li>
<p><span style="font-size:medium;">One of the primary things that keeps changing in the SharePoint Online master page is the Office 365 suite navigation, including the app launcher. From what I can tell, most of this rendering is done dynamically with JavaScript so as long as they continue to rev the referenced code and nothing specific in the master page itself, you will most likely stay fairly up-to-date there without any work of your own. As a matter of fact, I am hoping that is a model they move to more broadly for providing updates to these master pages.</span></p>
</li>
</ul>
<p><span style="font-family:Calibri;font-size:medium;">&nbsp;</span></p>
<p><i><span style="font-family:Calibri;font-size:medium;">Thank you to </span></i><a href="https://twitter.com/Bob1German"><i><span style="color:#0563c1;font-family:Calibri;font-size:medium;">@Bob1German</span></i></a><i><span style="font-family:Calibri;font-size:medium;"> for his review of this content.</span></i></p>
<p><b><span style="font-family:Calibri;font-size:medium;">&nbsp;</span></b></p>
<p></p>]]></content:encoded>
    </item>
    <item>
      <title>Updating your SharePoint Master Page in SharePoint Online</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/updating-your-sharepoint-master-page-in-sharepoint-online</link>
      <pubDate>Thu, 28 May 2015 06:36:41 GMT</pubDate>
      <dc:creator><![CDATA[pjsummersjr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2015/05/28/updating-your-sharepoint-master-page-in-sharepoint-online/</guid>
      <description><![CDATA[In this post, I am going to describe how I took a heavily customized SharePoint Online (SPO) master...]]></description>
      <content:encoded><![CDATA[<p>In this post, I am going to describe how I took a heavily customized SharePoint Online (SPO) master page that had been left behind in terms of Office 365 updates and brought it back from the dark ages. This is a bit off-topic for this blog but since I don’t contribute to any other blogs, I decided to temporarily hijack it.</p> <p>First, your mileage will vary with the specifics I provide here. Depending on the point in time you customized your master page and the customizations you made to it, you may have to do a deeper analysis. However, I hope you will benefit from the process I followed. </p> <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/image_630C1F68.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/image_5F00_630C1F68.png"><img title="image" style="border-top:0px;border-right:0px;background-image:none;border-bottom:0px;padding-top:0px;padding-left:0px;border-left:0px;display:inline;padding-right:0px;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/image_thumb_096E02B4.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/image_5F00_thumb_5F00_096E02B4.png" width="580" height="16" /></a></p> <h6><em>Before</em></h6> <h2>The Process</h2> <p>The first thing I did was download the latest master page from <strong>a new site collection in SharePoint Online</strong> and compared it with our customized master page using WinMerge. This was pretty tedious and as someone who has only done limited customizations of master pages, it proved not to be very effective. My breakthrough came when I was pointed to this <a href="http://startermasterpages.codeplex.com/releases/view/97062">CodePlex project</a> by Randy Drisgill. In this project, he dissects and labels the various elements of the master page. The samples he provides aren’t up-to-date with SPO but they still helped me decompose the elements of our master page and compare that to similar sections of the latest master page I pulled from SPO.</p> <p>Ultimately, I zeroed in on the HTML <em>div</em> with the <em>id=’&#39;suiteBar” </em>in both master pages. In the latest version, you’ll see that this <em>div</em> is wrapped in two <em>SharePoint </em>custom controls, <em>AjaxDelta </em>and <em>FlightedContent</em>. The latter really caught my eye.</p> <p>Once I picked these notable discrepancies out, I reviewed the markup within them and felt pretty confident that I could essentially replace everything within the <em>suiteBar </em>div with the content contained in, and including, the <em>SharePoint </em>custom control, <em>AjaxDelta.</em> I also had to register the following two tag prefixes:</p> <p><font color="#0000ff" face="Courier New">&lt;%@ Register TagPrefix=&quot;wssucmui&quot; TagName=&quot;MUISelector&quot; Src=&quot;~/_controltemplates/15/MUISelector.ascx&quot;%&gt;</font></p> <p><font face="Courier New"><br /><font color="#0000ff">&lt;%@ Register TagPrefix=&quot;wssucw&quot; TagName=&quot;Welcome&quot; src=&quot;~/_controltemplates/15/Welcome.ascx&quot; %&gt;</font></font></p> <h2></h2> <h2>Roll Out</h2> <p>The development process for Office 365 is still an evolving story. Some companies are using separate tenants for dev, test, etc. while others are simply leveraging separate site collections within their tenant. For this, I am using a separate site collection, which serves my needs pretty well. I was able to configure a new site collection with the customizations from our production site collection by exporting a design package from the production site collection and importing it into the test environment. This created an apples-to-apples environment for testing. I copied the updated master page over the custom one and the new suite bar appeared.</p> <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/image_12C9C7E8.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/image_5F00_12C9C7E8.png"><img title="image" style="border-top:0px;border-right:0px;background-image:none;border-bottom:0px;padding-top:0px;padding-left:0px;border-left:0px;display:inline;padding-right:0px;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/image_thumb_202FDAEE.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/image_5F00_thumb_5F00_202FDAEE.png" width="582" height="23" /></a></p> <p><em>After</em></p> <p>For our next step, we’re going to push the update into one of our other affected production site collections and let users hammer it. Since this is only a subset of our sites, if there are issues that we have not yet discovered, hopefully the impact will be minimal. Once we’re comfortable there, we’ll push to our other five or six site collections. Unfortunately, our main site collection is also our most complex so we’re going to push there last and dedicate time for our internal team to hammer at it and identify issues before the general user base gets at it.</p> <p>Hope this helps. Any questions, comments or feedback are welcome.</p>]]></content:encoded>
    </item>
    <item>
      <title>SharePoint Search Architecture @ Ignite 2015</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/sharepoint-search-architecture-ignite-2015</link>
      <pubDate>Mon, 04 May 2015 15:57:13 GMT</pubDate>
      <dc:creator><![CDATA[pjsummersjr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2015/05/04/sharepoint-search-architecture-ignite-2015/</guid>
      <description><![CDATA[For those of you here at Microsoft Ignite, welcome! It&#39;s really exciting to be part of this...]]></description>
      <content:encoded><![CDATA[<p>For those of you here at <a href="http://ignite.microsoft.com/#fbid=eQ-QRmT_TyZ">Microsoft Ignite</a>, welcome! It&#39;s really exciting to be part of this massive event and with only a day under our belts, we&#39;ve already seen some really cool announcements, not the least of which is the <a href="http://blogs.office.com/2015/05/04/modern-productivity-office-news-at-ignite/">continued innovation on the Office Graph and Delve</a>.  <p>On Friday afternoon, Dan Benson and I will be presenting on SharePoint Search architecture. We are going to talk about how you can ensure your enterprise search capabilities can scale and be available all the time. Please don’t read too much into our timeslot. With the awesomeness of Office 365, this might seem like a moot topic but the reality is that most enterprises still require some investment in their on-premises architecture to support legacy applications and content that is not quite ready for the cloud. SharePoint Search provides the most robust bridge through its hybrid capabilities to ensure a seamless user experience for accessing on-premises and cloud content. So, please come join us to learn how your on-premises infrastructure can scale to meet the demands of your business!  <p>&nbsp;</p> <table cellspacing="0" cellpadding="2" width="583" border="0"> <tbody> <tr> <td valign="top" width="581"><em>At the time of posting, there was an issue with the <a href="http://ignite.microsoft.com/Sessions">conference scheduling tool</a>. I will update the post as soon as possible with a direct link to our presentation. For now, go search for “Summers” under the speaker tab of the search interface and you’ll find a link to our presentation.</em></td></tr></tbody></table> <p>In advance of the presentation, I wanted to post some of the materials we&#39;ll be showing. Specifically, we&#39;ll be walking through a few different PowerShell scripts for defining and deploying your initial search topology and then expanding that initial topology to support the growing demands of your business. Additionally, we built a simple JavaScript tool for monitoring the health of your search system. For all of these, the code is simple at best, flaky at worst so please use at your own risk. However, we are typically asked for access to the code we show during our presentations so I thought I would provide it in advance rather than accepting a bunch of business cards and losing track of my promise to post the code later.  <p>If you&#39;re not attending this week, please look for our presentation on <a href="https://channel9.msdn.com">Channel9</a> once the conference is over. I will try to update this post with a direct link once it is available.  <p>Both the PowerShell scripts and search monitoring code are accessible on this <a href="http://1drv.ms/1OVjt0Q">OneDrive share</a>.  <p>For the search monitoring code, I plan to follow this post up with another post detailing how to deploy it. Bear in mind that it references 3rd party libraries but those are not included in my downloads. Also, the SP.Search.js code is something I’ve been working on here and there for some time. It’s also accessible on GitHub <a href="https://github.com/pjsummersjr/spsearchjs">here</a>. At this very moment, the code I posted to my OneDrive might be more up-to-date than the GitHub repo.</p> <p>I&#39;m excited about our presentation on Friday and for those of you still in town, I hope you&#39;ll stop by to see us. Last, if you&#39;re interested in any of my insights as an attendee, feel free to <a href="https://twitter.com/pjsummersjr">follow me on Twitter</a>.  </p></p></p></p></p></p>]]></content:encoded>
    </item>
    <item>
      <title>Building Custom Display Templates for OpenSearch Content</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/building-custom-display-templates-for-opensearch-content</link>
      <pubDate>Thu, 21 Aug 2014 13:42:17 GMT</pubDate>
      <dc:creator><![CDATA[pjsummersjr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2014/08/21/building-custom-display-templates-for-opensearch-content/</guid>
      <description><![CDATA[One of the less-used features of SharePoint Search (2013 or SPO) is the ability to federate to...]]></description>
      <content:encoded><![CDATA[<p><font size="2">One of the less-used features of SharePoint Search (2013 or SPO) is the ability to federate to non-SharePoint sources that support the </font><a href="http://www.opensearch.org/Home" target="_blank"><font size="2">OpenSearch</font></a><font size="2"> 1.1 protocol. Moreover, there isn’t a lot of documentation out there about what to do with those results once you have them or how to format them to fit in with the design of your SharePoint site.</font></p> <p><font size="2">In this post, I will show you how to build a custom display template using a federated result coming from an OpenSearch source.</font></p> <h2></h2> <h2>OpenSearch Result Structure</h2> <p><font size="2">As I started to dive into this, the first question I had was <em>what managed properties are returned when going to an OpenSearch source? </em>Using the </font><a href="https://sp2013searchtool.codeplex.com/" target="_blank"><font size="2">search query tool</font></a><font size="2">, I was able to see that the default MP’s returned with a federated result are:</font></p> <ul> <li><font size="2">HitHighlightedSummary</font></li> <li><font size="2">LastModifiedTime</font></li> <li><font size="2">OpenSearchSingleResultXML</font></li> <li><font size="2">Path</font></li> <li><font size="2">piSearchResultId</font></li> <li><font size="2">RenderTemplateId</font></li> <li><font size="2">ResultTypeId</font></li> <li><font size="2">Title</font></li></ul> <p><font size="2">The two most interesting properties in my opinion were the <em>HitHighlightedSummary</em> and the <em>OpenSearchSingleResultXML</em>. The former, also known as the dynamic teaser, should provide a snippet of the content that is relevant to the query. In my observation, however, it’s really just a snippet of the first sentence of the article so not a true dynamic teaser. The latter MP provides some raw XML about the document. Worth noting is that the <em>HitHighlightedSummary</em> seems to match the <em>description </em>sub-element of that XML. </font></p> <p><font size="2">This XML provides two other elements that I think might provide some value to our result display. </font></p> <ol> <li><font size="2">PubDate: While this is repeated in my <em>LastModifiedTime</em> managed property, it’s already nicely formatted for me in the raw result.</font></li> <li><a><font size="2">News:Source</font></a><font size="2"> – This provides me with the source of the content. Certainly this will be interesting to our user.</font></li></ol> <p><font size="2">Now that we know what our data looks like, let’s get to work building a custom display template.</font></p> <h2></h2> <h2>Initialize Your Template</h2> <p><font size="2">Go to the Design Manager and select Edit Display Templates. This will provide you with a list of display templates that are already deployed on your system. Download one of the existing templates and start by editing that. I would suggest choosing a simple template (Item_TwoLines is a good one) and working off of that.</font></p> <p><font size="2">Now that you have a template, the first thing you need to do is include the relevant managed properties in the template to ensure they’re available in the template.</font> </p><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><span><font color="#006400" size="2">&lt;mso:ManagedPropertyMapping msdt:dt=&quot;string&quot;&gt;</font></span></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><span><font color="#006400" size="2">&#39;Link URL&#39;{Link URL}:&#39;Path&#39;,&#39;Line 1&#39;{Line 1}:&#39;Title&#39;,&#39;Line 2&#39;{Line 2}:&#39;&#39;,</font></span></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><span><font color="#006400" size="2">&#39;FileExtension&#39;,&#39;SecondaryFileExtension&#39;,<font style="background-color:#ffff00;">&#39;OpenSearchSingleResultXML&#39;</font></font></span></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><span><font color="#006400" size="2">&lt;/mso:ManagedPropertyMapping&gt;</font></span>
</font></pre>
<p><font size="2">Feel free to modify the other MP’s in this mapping as well but for the sake of this post, we’re primarily concerned with including the <em>OpenSearchSingleResultXML </em>managed property.</font></p>
<p><font size="2">Now that we have that, we want to crack it open and get the information we need out of it using JavaScript from directly within our template. Here’s some sample code (relies on jQuery):</font></p><pre style="list-style-type:disc;background:white;line-height:normal;"><span><font face="Consolas"><font color="#006400" size="2">var osxml = $getItemValue(ctx, &quot;OpenSearchSingleResultXML&quot;);&nbsp; xmldoc = $.parseXML(osxml.value);
$xml = $(xmldoc);
$newssource = $xml.find(&quot;News\\:Source&quot;);
$newsdate = $xml.find(&quot;pubDate&quot;);
 
var thenewssource = $newssource.text();
var thenewsdate = $newsdate.text();</font></font></span></pre>
<p><span><font size="2">In the first three lines of code, I use jQuery to create a DOM object out of the XML returned in the search result’s <em>OpenSearchSingleResultXML </em>field. Then, I can use standard jQuery lookup mechanisms to find the element of the DOM I need. You’ll notice that to get the news source, I had to escape the colon character with double back slash. </font></span></p>
<p><span><font size="2">The final step is to render these data elements in the template display:</font></span></p><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><span><font color="#0000ff">&lt;</font></span><span><font color="#800000">div</font></span><font color="#000000">&nbsp;</font><span><font color="#ff0000">class</font></span><font color="#0000ff"><span>=</span><span>&quot;cbs-Detail&quot;</span></font><font color="#000000">&nbsp;</font><span><font color="#ff0000">id</font></span><font color="#0000ff"><span>=</span><span>&quot;_#= dataContainerId =#_&quot;</span><span>&gt;</span></font>
<font color="#000000">    </font><font style="background-color:#ffff00;"><span><font color="#0000ff">&lt;</font></span><span><font color="#800000">div</font></span><font color="#000000">&nbsp;</font><span><font color="#ff0000">class</font></span><font color="#0000ff"><span>=</span><span>&quot;&quot;</span><span>&gt;</span></font><font color="#000000">_#= thenewssource =#_</font><span><font color="#0000ff">&lt;/</font></span><span><font color="#800000">div</font></span><span><font color="#0000ff">&gt;</font></span></font>
<span><font color="#800000">    &lt;a</font></span><font color="#000000">&nbsp;</font><span><font color="#ff0000">class</font></span><font color="#0000ff"><span>=</span><span>&quot;cbs-Line1Link ms-displayBlock&quot;</span></font><font color="#000000">&nbsp;</font><span><font color="#ff0000">href</font></span><font color="#0000ff"><span>=</span><span>&quot;_#= linkURL =#_&quot;</span></font><font color="#000000">&nbsp;</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><span><font color="#ff0000">title</font></span><font color="#0000ff"><span>=</span><span>&quot;_#= $htmlEncode(line1.defaultValueRenderer(line1)) =#_&quot;</span></font><font color="#000000">&nbsp;</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><span><font color="#ff0000">id</font></span><font color="#0000ff"><span>=</span><span>&quot;_#= line1LinkId =#_&quot;</span><span>&gt;</span></font><font color="#000000">_#= line1 =#_</font><span><font color="#0000ff">&lt;/</font></span><span><font color="#800000">a</font></span><span><font color="#0000ff">&gt;</font></span>
</font></font><font face="Consolas"><font size="2"><span><font color="#006400">    &lt;!—#_&nbsp;&nbsp;&nbsp;&nbsp; if(!line2.isEmpty)&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _#—&gt;</font></span>
<span><font color="#0000ff">        &lt;</font></span><span><font color="#800000">div</font></span><font color="#000000">&nbsp;</font><span><font color="#ff0000">class</font></span><font color="#0000ff"><span>=</span><span>&quot;cbs-Line2&quot;</span></font><font color="#000000">&nbsp;</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><span><font color="#ff0000">title</font></span><font color="#0000ff"><span>=</span><span>&quot;_#= $htmlEncode(line2.defaultValueRenderer(line2)) =#_&quot;</span></font><font color="#000000">&nbsp;</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><span><font color="#ff0000">id</font></span><font color="#0000ff"><span>=</span><span>&quot;_#= line2Id =#_&quot;</span><span>&gt;</span></font><font color="#000000">_#= line2 =#_</font><span><font color="#0000ff">&lt;/</font></span><span><font color="#800000">div</font></span><span><font color="#0000ff">&gt;</font></span>
</font></font><font face="Consolas"><font size="2"><span><font color="#006400">        &lt;!--#_&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp; _#—&gt;</font></span>
<font color="#000000">    </font><font style="background-color:#ffff00;"><span><font color="#0000ff">&lt;</font></span><span><font color="#800000">div</font></span><font color="#000000">&nbsp;</font><span><font color="#ff0000">class</font></span><font color="#0000ff"><span>=</span><span>&quot;&quot;</span><span>&gt;</span></font><font color="#000000">_#= thenewsdate =#_</font><span><font color="#0000ff">&lt;/</font></span><span><font color="#800000">div</font></span><span><font color="#0000ff">&gt;</font></span></font>
<span><font color="#0000ff">&lt;/</font></span><span><font color="#800000">div</font></span><span><font color="#0000ff">&gt;</font></span></font>
</font></pre>
<p><font size="2">And that wraps it up. Now all you need to do it copy this template back into the Display Template library where we got it.&nbsp; You should rename the file so that it doesn’t overwrite the original template you copied and I suggest modifying the Title tag of the template so you can distinguish your new template from the original as well. I suggest something meaningful that describes the template, like “Open Search Bing News Item”.</font></p>
<p><font size="2">I haven’t included additional details on the plumbing required to deploy display templates themselves. This <a href="http://blogs.technet.com/b/speschka/archive/2012/07/23/using-query-rules-result-types-and-display-templates-for-a-custom-search-sales-report-in-sharepoint-2013.aspx" target="_blank">blog post</a> on Steve Peschka’s <a href="http://blogs.technet.com/b/speschka/" target="_blank">Share-n-dipity</a> blog provides a pretty robust explanation of that process.</font></p>]]></content:encoded>
    </item>
    <item>
      <title>Quick Hits: What to know when building search-driven SharePoint apps in SharePoint Online</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/quick-hits-what-to-know-when-building-search-driven-sharepoint-apps-in-sharepoint-online</link>
      <pubDate>Wed, 20 Aug 2014 18:28:48 GMT</pubDate>
      <dc:creator><![CDATA[pjsummersjr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2014/08/20/quick-hits-what-to-know-when-building-search-driven-sharepoint-apps-in-sharepoint-online/</guid>
      <description><![CDATA[Building search-driven apps in SharePoint Online can be a bit finicky. Actually, there’s a lot you...]]></description>
      <content:encoded><![CDATA[<p>Building search-driven apps in SharePoint Online can be a bit finicky. Actually, there’s a lot you should be aware of if your app is going to even leverage search at all but it’s all that more important if your data is getting updated a lot and you’re using search as your content retrieval mechanism.</p> <p>Here are a few tips to help manage your expectations:</p> <ol> <li>You have limited control over managed properties in SharePoint Online. For instance, you cannot create managed properties in SPO that are refinable. You have to use one of the out-of-box MP’s that are refinable. Luckily, there are a lots of them. From the managed property screen, search for “refinable” and you’ll get a list covering all data types.</li> <li>Indexing latency in SPO is variable and unpredictable. This is particularly an issue with testing but can also be an annoyance if, for instance, you’re inputting data on one screen and using search to retrieve that data on a subsequent screen. For retrieval of smaller data sets, still go at the list API’s. For larger sets of data, hopefully this indexing latency won’t impact you too much.</li> <li>When building a SharePoint-hosted app that runs in your SharePoint Online tenant, search requires tenant-scoped permissions. This means you must be a tenant admin to deploy the app. Many IT organizations might not allow an app to have this level of permission. Hopefully, we’ll see updates from the product that improve this situation. </li></ol> <p>That’s it for now. I’ll update this post as I am able to identify and document other issues.</p>]]></content:encoded>
    </item>
    <item>
      <title>Building a Search-Driven SharePoint App (I)–Setting a Foundation</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/building-a-search-driven-sharepoint-app-isetting-a-foundation</link>
      <pubDate>Tue, 08 Apr 2014 18:47:56 GMT</pubDate>
      <dc:creator><![CDATA[pjsummersjr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2014/04/08/building-a-search-driven-sharepoint-app-isetting-a-foundation/</guid>
      <description><![CDATA[At SharePoint Conference 2014 a few months ago, a good friend and colleague of mine did a...]]></description>
      <content:encoded><![CDATA[<p>At SharePoint Conference 2014 a few months ago, a good friend and colleague of mine did <a href="https://channel9.msdn.com/Events/SharePoint-Conference/2014/SPC402">a presentation</a> about how to build search-driven SharePoint apps. This topic remains interesting and relevant but I am starting to think we didn’t quite present it correctly. Our sad score reflects that.</p> <p>In the next few posts, I plan to do with a blog what I apparently couldn’t do while presenting to 500 people in Las Vegas: give the reader a foundation for consuming SharePoint search from their SharePoint 2013 (or Online) apps using JavaScript and the SharePoint REST API. The goal of this is not to create a conversation about how to use search in interesting ways. Rather, I want to provide a technical foundation so those that find those interesting ways aren’t starting from scratch. I probably won’t get every last nuance covered so please provide your feedback and questions in comments. And, to reiterate expectations properly, this set of posts will focus on using JavaScript and REST to build a SharePoint-hosted app. </p> <p>The subject of this first post will be creating some core object model components and getting search results back. </p> <p>The first thing you need to know&nbsp; is that there really is no JavaScript Object Model (JSOM) API for search. You, we, have to build that OM around the REST API. </p> <p>The Search JSOM that we want to build will contain the following:</p> <ul> <li>The query parameters accessible to us when submitting a search via the REST API  </li><li>The actions, or methods, we can execute when actually submitting that search  </li><li>The components of the response that we need to render our UI, including refiners, result blocks, etc.</li></ul> <p>First, I want to start by showing the targeted simplicity of our application logic code that will call this Search JSOM. If we’re building a simple results page, it can be as simple as the following:</p><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><span><font color="#0000ff">var</font></span><font color="#000000"> theQuery = </font><span><font color="#0000ff">new</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> Query();
theQuery.SPSite = </font><span><font color="#a31515">&quot;https://my.sharepoint-site.url&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;
theQuery.QueryText = $(</font><span><font color="#a31515">&#39;#searchBox&#39;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">).Value;
 
theQuery.RunSearch(
	</font><span><font color="#0000ff">function</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> (results) {&nbsp;&nbsp;&nbsp;&nbsp; alert(results);
	},
	</font><span><font color="#0000ff">function</font></span></font><font color="#000000" size="2"> (error) {&nbsp;&nbsp;&nbsp;&nbsp; alert(error);
	}
);</font></font></pre>
<p>Of course, there is some nuance in there which I hope we will make clear in this or subsequent blog posts but as you can see, with an API, we hide a lot of the complexity of the search call and response processing.</p>
<p>Now that we know what our basic search call should look like, let’s start building this Query object in JavaScript by creating a JavaScript file called “SP.Search.js” and adding the following code:</p><pre style="list-style-type:disc;background:white;line-height:normal;"><span><font color="#0000ff" size="2" face="Consolas">function</font></span><font face="Consolas"><font size="2"><font color="#000000"> Query() {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre>
<blockquote><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><span><font color="#0000ff">var</font></span><font color="#000000"> self = </font><span><font color="#0000ff">this</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.SPSite = </font><span><font color="#a31515">&quot;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.SearchApiPath = </font><span><font color="#a31515">&quot;/_api/search/query&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.QueryText = </font><span><font color="#a31515">&quot;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.SourceId = </font><span><font color="#a31515">&quot;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.SortFields = </font><span><font color="#a31515">&quot;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.SelectProperties = </font><span><font color="#a31515">&quot;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.Refiners = </font><span><font color="#a31515">&quot;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.RefinementFilters = [];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.RankingModelId = </font><span><font color="#a31515">&quot;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.StartRow = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.RowLimit = 10;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.EnableStemming = </font><span><font color="#a31515">&quot;true&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.EnablePhonetic = </font><span><font color="#a31515">&quot;true&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.EnableFQL = </font><span><font color="#a31515">&quot;false&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.EnableQueryRules = </font><span><font color="#a31515">&quot;true&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.RequestMethod = </font><span><font color="#a31515">&quot;GET&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.RequestContentType = </font><span><font color="#a31515">&quot;application/json;odata=verbose&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font color="#000000" size="2"></font></font>&nbsp;</pre></blockquote>
<p><font face="Segoe UI">This code encapsulates the query parameters we can submit to the search engine via the REST API. It’s not 100% exhaustive but it hits the critical query parameters. It also sets some defaults for less-often used parameters.</font></p>
<p><font face="Segoe UI">For a full list of the query parameters available via the REST API, please check out <a href="http://blogs.msdn.com/b/nadeemis/archive/2012/10/21/how-to-postquery-in-sharepoint-2013-search-rest-api.aspx">Nadeem Ishqair’s EXCELLENT blog on the topic</a>. I’m not going to go through the effort of explaining each parameter as Nadeem’s blog does that already. However, if you need clarification, please do not hesitate to post to comments.</font></p>
<p>Once I have the set of parameters to submit to the search engine, I build an HTTP request string to send off to the REST end point. I do that in the BuildQuery method. However, the API client doesn’t really need to know much about this method. This is an abstraction that my API provides but I show it here for your understanding (and feedback):</p><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.BuildQuery = </font><span><font color="#0000ff">function</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> () {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><span><font color="#0000ff">    var</font></span><font color="#000000"> queryExpr = </font><span><font color="#a31515">&quot;querytext=&#39;&quot;</font></span><font color="#000000"> + self.QueryText + </font><span><font color="#a31515">&quot;&#39;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    queryExpr += </font><span><font color="#a31515">&quot;&amp;selectproperties=&#39;&quot;</font></span><font color="#000000"> + self.SelectProperties + </font><span><font color="#a31515">&quot;&#39;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    queryExpr += </font><span><font color="#a31515">&quot;&amp;refiners=&#39;&quot;</font></span><font color="#000000"> + self.Refiners + </font><span><font color="#a31515">&quot;&#39;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    </font><span><font color="#0000ff">if</font></span><font color="#000000"> (self.SourceId != </font><span><font color="#a31515">&quot;&quot;</font></span><font color="#000000">) queryExpr += </font><span><font color="#a31515">&quot;&amp;sourceid=&#39;&quot;</font></span><font color="#000000"> + self.SourceId + </font><span><font color="#a31515">&quot;&#39;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    </font><span><font color="#0000ff">if</font></span><font color="#000000"> (self.SortFields != </font><span><font color="#0000ff">null</font></span><font color="#000000"> &amp;&amp; self.SortFields != </font><span><font color="#a31515">&quot;&quot;</font></span><font color="#000000">) queryExpr += </font><span><font color="#a31515">&quot;&amp;sortlist=&#39;&quot;</font></span><font color="#000000"> + self.SortFields + </font><span><font color="#a31515">&quot;&#39;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    </font><span><font color="#0000ff">if</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> (self.RefinementFilters.length &gt; 0) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">        </font><span><font color="#0000ff">var</font></span><font color="#000000"> refinementStr = </font><span><font color="#a31515">&quot;&amp;refinementFilters=&#39;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">        </font><span><font color="#0000ff">for</font></span><font color="#000000"> (</font><span><font color="#0000ff">var</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> i = 0; i &lt; self.RefinementFilters.length; i++) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">            </font><span><font color="#0000ff">if</font></span><font color="#000000"> (self.RefinementFilters.length &gt; 1 &amp;&amp; i == 0) refinementStr += </font><span><font color="#a31515">&quot;and(&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">            </font><span><font color="#0000ff">if</font></span><font color="#000000"> (i &gt; 0) refinementStr += </font><span><font color="#a31515">&quot;,&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">            refinementStr += self.RefinementFilters[i].PropertyName + </font><span><font color="#a31515">&quot;:ends-with(\&quot;&quot;</font></span><font color="#000000"> + self.RefinementFilters[i].GetDisplayString(self.RefinementFilters[i].FilterValue) + </font><span><font color="#a31515">&quot;\&quot;)&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">        }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">        </font><span><font color="#0000ff">if</font></span><font color="#000000"> (self.RefinementFilters.length &gt; 1) refinementStr += </font><span><font color="#a31515">&quot;)&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">        queryExpr += refinementStr + </font><span><font color="#a31515">&quot;&#39;&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    queryExpr += </font><span><font color="#a31515">&quot;&amp;startrow=&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> + self.StartRow;</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp; queryExpr += </font><span><font color="#a31515">&quot;&amp;rowlimit=&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> + self.RowLimit;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp; queryExpr += </font><span><font color="#a31515">&quot;&amp;enablefql=&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> + self.EnableFQL;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp; queryExpr += </font><span><font color="#a31515">&quot;&amp;enablequeryrules=&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> + self.EnableQueryRules;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    queryExpr += </font><span><font color="#a31515">&quot;&amp;enablephonetic=&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> + self.EnablePhonetic;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    queryExpr += </font><span><font color="#a31515">&quot;&amp;enablestemming=&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> + self.EnableStemming;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">    </font><span><font color="#0000ff">return</font></span></font><font color="#000000" size="2"> queryExpr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font color="#000000" size="2">};</font></font></pre>
<p>There is quite a bit of logic going on this. I hope the reader can follow most of it. What might be a bit confusing is the 10 lines of code starting with <em>if(self.RefinementFilters.length…</em>. When we submit refinement filters to the search engine as part of a REST call, it must be formatted as a <a href="http://msdn.microsoft.com/en-us/library/office/ff394606(v=office.15).aspx">valid FQL expression</a>. This is an odd requirement for a number of reasons, least of which being the fact that the default query text language is KQL. However, it’s required nonetheless and it happens to surface a lot of potential (a topic for another post -- sorry).</p>
<p>Moving on, the next thing we need to do is actually make a call to the REST endpoint. The following code does that using a standard JQuery AJAX request:</p><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">self.RunSearch = </font><span><font color="#0000ff">function</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> (successFunc, failureFunc) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">     </font><span><font color="#0000ff">var</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> queryParamStr = self.BuildQuery();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">     </font><span><font color="#0000ff">var</font></span><font color="#000000"> searchUrl = self.SPSite + self.SearchApiPath + </font><span><font color="#a31515">&quot;?&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> + queryParamStr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">     $.ajax({</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url: searchUrl,</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: self.RequestMethod,</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contentType: self.RequestContentType,</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; headers: {</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span><font color="#a31515">&quot;Accept&quot;</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000">: self.RequestContentType,</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; success: </font><span><font color="#0000ff">function</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> (data) {</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><span><font color="#0000ff">var</font></span><font color="#000000"> theSearchResults = </font><span><font color="#0000ff">new</font></span></font></font><font face="Consolas"><font size="2"><font color="#000000"> SearchResults();</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; theSearchResults.RawJson = data;</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; theSearchResults.BuildResultObject();</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; successFunc(theSearchResults);</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },</font></font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font size="2"><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error: </font><span><font color="#0000ff">function</font></span></font><font color="#000000" size="2"> (data) { failureFunc(data);</font></font><font face="Consolas"><font color="#000000" size="2">}</font></font><font face="Consolas"><font color="#000000" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font color="#000000" size="2">    });&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></pre><pre style="list-style-type:disc;background:white;line-height:normal;"><font face="Consolas"><font color="#000000" size="2">};</font></font></pre>
<p>The <em>data</em> argument submitted to the success callback function is a big JSON object representing the response from the search engine. That success function does a number of things, including calling methods to deserialize the response as well as invoke the callback method that is passed into the RunSearch method itself. All topics for the next post.</p>
<p>If you are an experienced SharePoint App developer, one thing that might surprise you is that this code does not leverage the RequestExecutor to handle the cross-domain call. Well, search happens to be somewhat unique in this respect in that it can make a call to the local domain (the App Web) and still consume the farm/tenant’s search service. This is because search is a service that spans the entire farm/tenant scope. All that said, I plan to refactor this code to use the proper cross-domain calls, mainly to account for the variety of scenarios and code reuse objectives that might surface. I’ll make sure this post reflects those code updates.</p>
<p>The core objective of this post is to start to build the foundation for a JavaScript object model API for SharePoint Search (2013 and Online). In this post, we defined the basic properties of a Query that reflect a search as well as the methods used to actually make the call. </p>
<p>In my next post, I will talk about how to take that JSON response, process it and return it to the calling application so that the data can be rendered for the user.</p>
<p>Did this post help you? What additional detail are you looking for? Please provide feedback, good and bad, so that I can refine and improve the content going forward.</p>
<p>P.S. I am still trying to figure out why my code sections have all the lines. I beg your patience.</p>
<p><em>Update: I have been able to get properly formatted code but have lost line numbers. Gonna live with that for now. No other updates to this post.</em></p>]]></content:encoded>
    </item>
    <item>
      <title>SharePoint Online crawl/indexing latency</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/sharepoint-online-crawlindexing-latency</link>
      <pubDate>Wed, 11 Dec 2013 13:25:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt King - Search]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2013/12/11/sharepoint-online-crawlindexing-latency/</guid>
      <description><![CDATA[Compared to SharePoint 2013 on premise, working in SharePoint Online can be a little bit like...]]></description>
      <content:encoded><![CDATA[<p>Compared to SharePoint 2013 on premise, working in SharePoint Online can be a little bit like groping in the dark.&nbsp;&nbsp; To re-index content you can either:</p>
<ol>
<li>Edit the item</li>
<li>Go to the List Settings &ndash;&gt; Advanced settings page and click on the Reindex List button</li>
</ol>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/7120.image_79073896.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/7120.image_5F00_79073896.png"><img style="display: inline;" title="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/3021.image_thumb_6247F10D.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/3021.image_5F00_thumb_5F00_6247F10D.png" alt="image" width="332" height="108" border="0" /></a></p>
<p>Then you get to wait around for it to be indexed.&nbsp; Sometimes that can be quickly, other times not as quick.</p>
<p>While waiting around one day and playing with <a href="http://blogs.technet.com/b/searchguys/archive/2013/12/11/how-to-all-managed-properties-of-a-document.aspx">pulling all the managed properties</a> for my documents I ran into another interesting managed property called CrawlTime.&nbsp; This one doesn&rsquo;t come up if you search for it on the Managed Search Schema page, but it is there:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/0211.image_6FAE0413.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/0211.image_5F00_6FAE0413.png"><img style="display: inline;" title="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/1803.image_thumb_43FD3A17.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/1803.image_5F00_thumb_5F00_43FD3A17.png" alt="image" width="244" height="213" border="0" /></a></p>
<p>Through some playing around with it I&rsquo;ve determined that it is a date type property that is retrieve-only which is a bummer because being able to filter or sort your results by the date crawled would be <strong>very</strong> handy!</p>
<p>Nonetheless, it is better than nothing and applying a little PowerShell we can easily report on the indexing latency.&nbsp;&nbsp; Like <a href="http://blogs.technet.com/b/searchguys/archive/2013/12/11/how-to-all-managed-properties-of-a-document.aspx">we did for the managed properties</a>, run your query in the <a href="http://sp2013searchtool.codeplex.com/">Search Query Tool</a> and then copy the json off of the Raw tab.&nbsp; Then run this in PowerShell:</p>
<pre class="csharpcode">$obj = ConvertFrom-Json (Get-Clipboard)
$results = $obj.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results
<span class="kwrd">foreach</span> ($r <span class="kwrd">in</span> $results) {
    $title = ($r.cells.results | ? { $_.key -eq <span class="str">'Title'</span> }).Value
    $path = ($r.cells.results | ? { $_.key -eq <span class="str">'Path'</span> }).Value
    $modified = Get-Date ($r.cells.results | ? { $_.key -eq <span class="str">'Write'</span> }).Value
    $crawled = Get-Date ($r.cells.results | ? { $_.key -eq <span class="str">'CrawlTime'</span> }).Value
    $delta = $crawled - $modified
    write-host $title
    write-host <span class="str">" Modified: $modified"</span>
    write-host <span class="str">" Crawled: $crawled"</span>
    write-host <span class="str">" Index latency: $delta"</span>
}
</pre>
<p>You should get a report that looks something like this:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/7103.image_13D5EF54.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/7103.image_5F00_13D5EF54.png"><img style="display: inline;" title="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/6136.image_thumb_68252557.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/6136.image_5F00_thumb_5F00_68252557.png" alt="image" width="285" height="348" border="0" /></a></p>
<p>The first item took a little over an hour to index while the last one was just under 30 minutes.&nbsp; Note that the ones with the really long delay were indexed by a Reindex List request and therefor the indexing latency isn't applicable (because the items haven't changed so the modified time didn't get updated).&nbsp;</p>
<p>The PowerShell would be easy to adapt for other purposes.</p>
<p>Another idea I had was to create a tool that would periodically (every 10 minutes?) modify a list item and search for it.&nbsp; Using the CrawlTime one could build a fairly accurate chart showing SPO indexing latency :)</p>]]></content:encoded>
    </item>
    <item>
      <title>How to find all managed properties of a document</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/how-to-find-all-managed-properties-of-a-document</link>
      <pubDate>Tue, 10 Dec 2013 17:38:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt King - Search]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2013/12/10/how-to-find-all-managed-properties-of-a-document/</guid>
      <description><![CDATA[When working with SharePoint search it is often helpful to figure out all of the managed properties...]]></description>
      <content:encoded><![CDATA[<p>When working with SharePoint search it is often helpful to figure out all of the managed properties that are populated for a given set of documents. With SharePoint 2013 on premise, you can use the Content Enrichment Web Service (CEWS) and its debug mode to get at (almost) all of the managed properties for a document as it is being indexed.&nbsp; This requires a bit of setup to get the web service in place and then you need to feed your documents in to be indexed.&nbsp; But what if you are interested in items already indexed? Or what if you are working with SharePoint Online where you don't have the CEWS?</p>
<p>SharePoint 2013 has a managed property called "ManagedProperties" that can be used instead. The ManagedProperties managed property is populated with the names of all the managed properties that have values for that document. The only trick is that this managed property is not retrievable, it can only be used as a refiner.&nbsp;</p>
<p>You could add this refiner to your search center, but I have found it much more useful to explore using the <a href="http://sp2013searchtool.codeplex.com/">SharePoint 2013 Search Query Tool</a> and PowerShell.</p>
<p>To get started, download and fire up the <a href="http://sp2013searchtool.codeplex.com/">Search Query Tool</a>. Authenticate with you site and set up a query that returns the document(s) you are interested in.&nbsp; Open a PowerShell window.</p>
<p>In the Query block of the Search Query Tool application configure the Refiners to be</p>
<blockquote>
<p>managedproperties(filter=600/0/*)</p>
</blockquote>
<p>and re-run your query. On the Refinement Results tab you should now see the managedproperties refiner that will have a big list of refinements. For example:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/5086.clip_image001_59372857.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/5086.clip_5F00_image001_5F00_59372857.png"><img style="display: inline;" title="clip_image001" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/1614.clip_image001_thumb_1AD3F555.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/1614.clip_5F00_image001_5F00_thumb_5F00_1AD3F555.png" alt="clip_image001" width="383" height="627" border="0" /></a></p>
<p>Scrolling through this list can often be helpful in itself, but sometimes it is nice to be able to see the values of all these managed properties and hand cutting-and-pasting can be quite cumbersome. The following technique can be used to make things much easier.</p>
<p>Go to the Raw tab and at the bottom you will see a big bunch of JSON like:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/2100.clip_image002_00FFBF26.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/2100.clip_5F00_image002_5F00_00FFBF26.png"><img style="display: inline;" title="clip_image002" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/6431.clip_image002_thumb_2A0A5E22.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/6431.clip_5F00_image002_5F00_thumb_5F00_2A0A5E22.png" alt="clip_image002" width="632" height="196" border="0" /></a></p>
<p>Select and copy all of the JSON. Now open PowerShell:</p>
<pre class="csharpcode">$obj = $obj = ConvertFrom-Json (Get-Clipboard)
$r = $obj.d.query.PrimaryQueryResult.RefinementResults.Refiners.results | `
         ? { $_.name -eq <span class="str">'managedproperties'</span> }
$names = $r.Entries.results | % { $_.RefinementName } | sort
$names -join <span class="str">","</span> | Out-Clipboard
</pre>
<p>And now you can paste the list of mps separated by commas. Go back to the Search Query Tool and paste the list into the Select Properties box and run your search again. On the Primary Results tab you'll now see all of the (retrievable) managed properties. (Note: some managed properties still won't have values because they have been configured to be non-retrievable.)</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/1070.clip_image003_5E3E8768.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/1070.clip_5F00_image003_5F00_5E3E8768.png"><img style="display: inline;" title="clip_image003" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/8688.clip_image003_thumb_5D6B42E0.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/8688.clip_5F00_image003_5F00_thumb_5F00_5D6B42E0.png" alt="clip_image003" width="503" height="592" border="0" /></a></p>]]></content:encoded>
    </item>
    <item>
      <title>Multi-select refiners and taxonomy managed properties</title>
      <link>https://docs.microsoft.com/archive/blogs/searchguys/multi-select-refiners-and-taxonomy-managed-properties</link>
      <pubDate>Wed, 13 Nov 2013 08:29:50 GMT</pubDate>
      <dc:creator><![CDATA[Matt King - Search]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/searchguys/2013/11/13/multi-select-refiners-and-taxonomy-managed-properties/</guid>
      <description><![CDATA[In SharePoint 2013 you can use the “Multi-value Refinement Item” display template to allow users to...]]></description>
      <content:encoded><![CDATA[<p>In SharePoint 2013 you can use the “Multi-value Refinement Item” display template to allow users to choose multiple refinement values that will be searched for with OR logic.&#160; In the following example, when I click “Apply” the results will be narrowed to any that match Audit or CPO</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/0285.image_337B6626.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/0285.image_5F00_337B6626.png"><img title="image" style="display: inline;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/7658.image_thumb_67AF8F6C.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/7658.image_5F00_thumb_5F00_67AF8F6C.png" width="110" height="201" /></a> </p>  <p>The neat thing is the “Other Value” which allows users to enter their own values here that might not appear at the top of the refinement list.&#160; So in the next example, Apply will find results that match Audit, CPO or Tax</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/4540.image_2A2231A3.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/4540.image_5F00_2A2231A3.png"><img title="image" style="display: inline;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/2388.image_thumb_7BC8ABF5.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/2388.image_5F00_thumb_5F00_7BC8ABF5.png" width="159" height="219" /></a> </p>  <p>This works all well and good until you try it with a managed property populated from the Managed Metadata Term Store.&#160; Now the checkboxes will work but the Other Value will always return no results, even if you enter in the exact value that you see in the top refinement results.&#160;&#160; The reason for this is that the data in the refinement values is actually the unique identifier from the taxonomy </p>  <p><img alt="nav4.png" src="https://microsoft.sharepoint.com/teams/EnterpriseSearch/SiteAssets/SitePages/Community%20Home/nav4.png" /></p>  <p>and the Other Value is being searched for using the Equals() operator.&#160;&#160;&#160;&#160; You can see this by decoding the URL generated after clicking on Apply.&#160;&#160; Just clicking the “HR” check box shows that it is searching for the id portion only:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/4073.image_6509646C.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/4073.image_5F00_6509646C.png"><img title="image" style="display: inline;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/0677.image_thumb_0B6B47B8.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/0677.image_5F00_thumb_5F00_0B6B47B8.png" width="400" height="204" /></a> </p>  <p>while entering “HR” into the other box uses the equals() operator:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/8228.image_5490F371.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/8228.image_5F00_5490F371.png"><img title="image" style="display: inline;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/5824.image_thumb_08C51CB8.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/5824.image_5F00_thumb_5F00_08C51CB8.png" width="265" height="147" /></a> </p>  <p>which clearly won’t match.</p>  <p>There is a workaround however.&#160; In the Filter_MultiValue_Body.html template there is an option to override the equals to instead just searches for the string:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/2605.image_51EAC871.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/2605.image_5F00_51EAC871.png"><img title="image" style="display: inline;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/5488.image_thumb_28768731.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/5488.image_5F00_thumb_5F00_28768731.png" width="645" height="253" /></a> </p>  <p>I haven’t (yet) figured out how to set the csr_useContains on the refinement control, but overriding the useContains variable in the template itself is easy enough and gets the job done:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/4237.image_5181262D.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/4237.image_5F00_5181262D.png"><img title="image" style="display: inline;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/93/78/metablogapi/8546.image_thumb_25D05C31.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-93-78-metablogapi/8546.image_5F00_thumb_5F00_25D05C31.png" width="325" height="196" /></a> </p>  <p>The only downside of this is that you could run into situations where you match more than you’d intended.&#160; But you can use wildcards which could be handy.</p>]]></content:encoded>
    </item>
  </channel>
</rss>