Creating Result Sources using PowerShell

This post describes how to create a search result source using PowerShell. The GUI is easy enough but scripting is optimal as you promote configurations across environments. I was compelled to write this post because I’ve found a few posts out on the internet that don’t appear to be correct.

As a pre-requisite, the user that runs the command needs to have rights on the Search Service application database. I didn’t go through the effort of identifying least privilege so I gave my user db_owner rights but that is somewhat consistent with the service account guidance on TechNet.

In any case, here’s the code:

 Add-PSSnapin Microsoft.SharePoint.PowerShell
  
$ssa = Get-SPEnterpriseSearchServiceApplication
$fedman = New-Object Microsoft.Office.Server.Search.Administration.Query.FederationManager($ssa)
  
$searchOwner = Get-SPEnterpriseSearchOwner -Level Ssa  
  
$resultSourceName = "Bing Search"
$urlTemplate = "https://www.bing.com/search?q={searchTerms}&format=rss&Market=en-Us"
$qT = "{searchTerms}"
$resultSource = $fedman.GetSourceByName($resultSourceName, $searchOwner)
if(!$resultSource){
    Write-Host "Result source does not exist. Creating."
    $resultSource = $fedman.CreateSource($searchOwner)
}
else { Write-Host "Using existing result source." }
  
$resultSource.Name =$resultSourceName
$resultSource.ProviderId = $fedman.ListProviders()['OpenSearch Provider'].Id
$resultSource.ConnectionUrlTemplate = $urlTemplate
$resultSource.CreateQueryTransform($queryProperties,$qT)
$resultSource.Commit()
  

A couple of highlights:

  1. On line 6, we create this SearchOwner object. This essentially defines the scope of the query rule. In this case, it’s a farm-scoped query rule. We could have set this at the site collection or site level as well. Doing that requires an additional parameter indicating which site or site collection it applies to.
  2. If you don’t have the correct database permissions on the Search Service application database, this code will blow up on line 19. You can also dump a list of all providers by executing $fedman.ListProviders().

I mentioned at the beginning of this post that other blogs I had read about this didn’t seem to quite get it right. Specifically, they used the federated source URL and parameter pattern (e.g. “https://www.bing.com/search?q={searchTerms}&format=rss&Market=en-Us”) and applied it as the query transform.

The query transform is a way of changing the {searchTerms}, but it is not the source of the query itself. You can see in my script that I have actually not changed those at all and am using the default value.