Create search topology with PowerShell - Part 2

In my recent post I described the initial configuration of a search topology. This posting will show you how to configure crawl and query topologies. To do this you need to run the following steps:

Step 1: Configure administrative component
Step 2: Creating new crawl topology
Step 3: Creating new crawl database
Step 4: Creating crawl components
Step 5: Activate the crawl topology
Step 6: Cleanup crawl objects
Step 7: Creating new query topology
Step 8: Creating new property database
Step 9: Configuring index partition
Step 10: Creating query component
Step 11: Activate the query topology
Step 12: Cleanup query objects

 This is how to run these steps with the appropriate PowerShell script:

 

$searchSA = "FARM01_ENTW_Enterprise Search"
$searchAdminCompData = "C:\MSS\SearchAdminComponent"
$searchAdminServer = "FARM01-DEV01"
$searchCrawlDBName = "FARM01_DEV08_EnterpriseSearchCrawlDB_00"
$searchCrawlDBServer = "SERVICE_ALIAS"
$allCrawlComponentServers = @("FARM01-DEV08")
$searchCrawlIndexLocation = "C:\MSS\Index"
$numIndexPartitions = 1
$searchPropertyDBName = "BTRX01_PROG08_EnterpriseSearchPropertyDB_00"
$searchPropertyDBServer = "SERVICE_ALIAS"

# Code
# ================
 
clear

# Start creating the new search configuration
# ===========================================

# Loading SharePoint Snapin
Add-PSSnapin Microsoft.SharePoint.PowerShell -ea SilentlyContinue

# Get existing components
$oldAdminComponent = Get-SPEnterpriseSearchAdministrationComponent -SearchApplication $searchSA
$oldCrawlTopology = Get-SPEnterpriseSearchCrawlTopology -SearchApplication $searchSA
$oldCrawlDatabase = Get-SPEnterpriseSearchCrawlDatabase -SearchApplication $searchSA
$oldCrawlComponent = Get-SPEnterpriseSearchCrawlComponent -CrawlTopology $oldCrawlTopology
$oldQueryTopology = Get-SpEnterpriseSearchQueryTopology -SearchApplication $searchSA
$oldPropertyDatabase = Get-SPEnterpriseSearchPropertyDatabase -SearchApplication $searchSA
$oldIndexPartition = Get-SPEnterpriseSearchIndexPartition -QueryTopology $oldQueryTopology
$oldQueryComponent = Get-SPEnterpriseSearchQueryComponent -QueryTopology $oldQueryTopology
 

# Get the search service instance
$SearchServiceInstance = Get-SPEnterpriseSearchServiceInstance
 
if ($SearchServiceInstance.Status -ne "Online") {
  Write-Host "Search Service Instance not started. Exiting..."
  exit
} else {

  # ------------------------------------------------------------
  # CRAWL CONFIGURATION
  # ------------------------------------------------------------
 
  # Step 1: Configure administrative component
  # ==========================================
  Write-Host "Configuring administrative component" -backgroundcolor blue
  $admComp = Get-SPEnterpriseSearchAdministrationComponent -SearchApplication $searchSA
  $SearchServiceApp = Get-SPEnterpriseSearchServiceApplication $searchSA
  Set-SPEnterpriseSearchAdministrationComponent -Identity $admComp -SearchApplication $searchSA -StoragePath $searchAdminCompData -SearchServiceInstance $searchAdminServer
 
  # Step 2: Creating new crawl topology
  # ===================================
  Write-Host "Creating new crawl topology" -backgroundcolor blue
  $crawlTopology = New-SPEnterpriseSearchCrawlTopology -SearchApplication $searchSA
  Write-Host ("New topology ID: {0}" -f $crawlTopology.Id)
  Write-Host ("New topology state: {0}" -f $crawlTopology.State)
 
  # Step 3: Creating new crawl database
  # ===================================
  Write-Host "Creating new crawl database" -backgroundcolor blue
  $crawlDatabase = New-SPEnterpriseSearchCrawlDatabase -SearchApplication $searchSA -DatabaseName $searchCrawlDBName -DatabaseServer $searchCrawlDBServer
  Write-Host ("New database ID: {0}" -f $crawlDatabase.Id)
  Write-Host ("New database Name: {0}" -f $crawlDatabase.Name)
 
  # Step 4: Creating crawl components
  # =================================
  Write-Host "Creating new crawl component" -backgroundcolor blue
  foreach ($oneCrawlComponentServer in $allCrawlComponentServers) {
    Write-Host ("Crawl Component Server: {0}" -f $oneCrawlComponentServer)
    $crawlComponent = New-SPEnterpriseSearchCrawlComponent -CrawlTopology $crawlTopology -CrawlDatabase $crawlDatabase -SearchServiceInstance $oneCrawlComponentServer -IndexLocation $searchCrawlIndexLocation
    Write-Host ("New crawl component ID: {0}" -f $crawlComponent.Id)
  }

  # Step 5: Activate the crawl topology
  # ===================================
  Write-Host "Trying to activate the new topology. This might take some time..." -backgroundcolor blue
  $crawlTopology | Set-SPEnterpriseSearchCrawlTopology -Active

  $allCrawlTopologies = Get-SPEnterpriseSearchCrawlTopology -SearchApplication $searchSA | ? {$_.State -eq "Deactivating"}
  while ( !([String]::IsNullOrEmpty($allCrawlTopologies))) {
    $timestamp = [System.DateTime]::Now
    Write-Host ("Found {0} topologies being deactivated..." -f (Get-SPEnterpriseSearchCrawlTopology -SearchApplication $searchSA | ? {$_.State -eq "Deactivating"}).Count)
    Sleep 5
    $allCrawlTopologies = Get-SPEnterpriseSearchCrawlTopology -SearchApplication $searchSA | ? {$_.State -eq "Deactivating"}
  }
 
  # Step 6: Cleanup crawl objects
  # ===============================
  Write-Host "Removing old crawl topologies"
  $allInactiveCrawlTopologies = Get-SPEnterpriseSearchCrawlTopology -SearchApplication $searchSA | ? {$_.State -eq "Inactive"} | % {
    Write-Host ("Removing old crawl topoloy with ID '{0}'" -f $_.Id)
    $_ | Remove-SPEnterpriseSearchCrawlTopology -confirm:$false
  } 
  Write-Host "Removing old crawl databases"
  $allUnboundDatabases = Get-SPEnterpriseSearchCrawlDatabase -SearchApplication $searchSA | ? {$_.CrawlComponents.Count -eq 0} | % {
    Write-Host ("Removing old crawl database with ID '{0}'" -f $_.Id)
    $_ | Remove-SPEnterpriseSearchCrawlDatabase -confirm:$false
  }

  # ------------------------------------------------------------
  # QUERY CONFIGURATION
  # ------------------------------------------------------------
 
  # Step 7: Creating new query topology
  # ===================================
  Write-Host "Creating new query topology" -backgroundcolor blue
  $queryTopology = New-SPEnterpriseSearchQueryTopology -SearchApplication $searchSA -Partitions $numIndexPartitions
  Write-Host ("New topology ID: {0}" -f $queryTopology.Id)
  Write-Host ("New topology state: {0}" -f $queryTopology.State)

  # Step 8: Creating new property database
  # ===================================
  Write-Host "Creating new property database" -backgroundcolor blue
  $propertyDatabase = New-SPEnterpriseSearchPropertyDatabase -SearchApplication $searchSA -DatabaseName $searchPropertyDBName -DatabaseServer $searchPropertyDBServer
  Write-Host ("New database ID: {0}" -f $propertyDatabase.Id)
  Write-Host ("New database Name: {0}" -f $propertyDatabase.Name)

  # Step 9: Configuring index partition
  # ===================================
  Write-Host "Configuring index partition" -backgroundcolor blue
  $indexPartition = Get-SPEnterpriseSearchIndexPartition -QueryTopology $queryTopology
  $indexPartition | Set-SPEnterpriseSearchIndexPartition -PropertyDatabase $propertyDatabase

  # Step 10: Creating query component
  # ================================
  Write-Host "Creating query component" -backgroundcolor blue
  Get-SPEnterpriseSearchQueryComponent -QueryTopology $queryTopology
  $queryComponent = New-SPEnterpriseSearchQuerycomponent -QueryTopology $queryTopology -IndexPartition $indexPartition -SearchServiceInstance $SearchServiceInstance

  # Step 11: Activate the query topology
  # ====================================
  Write-Host "Trying to activate the new query topology" -backgroundcolor blue
  $queryTopology | Set-SPEnterpriseSearchQueryTopology -Active
 
  $allQueryTopologies = Get-SPEnterpriseSearchQueryTopology -SearchApplication $searchSA | ? {$_.State -eq "Deactivating"}
  while ( !([String]::IsNullOrEmpty($allQueryTopologies))) {
    $timestamp = [System.DateTime]::Now
    Write-Host ("[{0}] Found {1} topologies being deactivated..." -f $timestamp, (Get-SPEnterpriseSearchQueryTopology -SearchApplication $searchSA | ? {$_.State -eq "Deactivating"}).Count)
    Sleep 5
    $allQueryTopologies = Get-SPEnterpriseSearchQueryTopology -SearchApplication $searchSA | ? {$_.State -eq "Deactivating"}
  }
 
  # Step 12: Cleanup query objects
  # ===============================
  Write-Host ("Removing old query topoloy with ID '{0}'" -f $oldQueryTopology.Id)
  $allInactiveQueryTopologies = Get-SPEnterpriseSearchQueryTopology -SearchApplication $searchSA | ? {$_.State -eq "Inactive"} | % {
    Write-Host ("Removing old query topology with ID '{0}'" -f $_.Id)
    $_ | Remove-SPEnterpriseSearchQueryTopology -confirm:$false
  }
 
  Write-Host ("Removing old property database with ID '{0}'" -f $oldPropertyDatabase.Id)
  $allUnboundDatabases = Get-SPEnterpriseSearchPropertyDatabase -SearchApplication $searchSA | ? {$_.IndexPartitions.Count -eq 0} | % {
    Write-Host ("Removing old property database with ID '{0}'" -f $_.Id)
    $_ | Remove-SPEnterpriseSearchPropertyDatabase -confirm:$false
  }
 
} # if..else
 

I've tested that script on multiple Single-Server-Installations successfully but did not find the time to fully test this on a farm deployment. So any feedback on that is highle appreciated if you run this script on a farm.