Creating extended Search topology in Sharepoint 2013


If you are creating a Search service application in SharePoint 2013 and want to create an extedned search topology, the only choice you have is “PowerShell”.  Althought the process looks bit complex but if you spent few minutes in the PowerShell script below it will become very simply.

Below script uses a 9 server Search Toplogy where we have the following configuration

  • 3 Query Processing Components
  • 3 Index Partitions and their Replicas
  • 2 Admin Components
  • 2 Crawl Components
  • 2 Analytic Components
  • 2 Content Processing Components

You can see that we have redundant search components.  with this topology we were planning to cover 30 content sources with over 40 Million items in in the index.

First on the root define the Servers and mention their role.  I used an Excel sheet first then moved them in Powershell

Note: If you are extending an existing which already has index.  it is good to RESET Index.  Additonally you can pause the Search Service Applicaton and then resume it after new topology.

$hostA = Get-SPEnterpriseSearchServiceInstance -Identity “SERVER135" #Query Processing -  Index 0
$hostB = Get-SPEnterpriseSearchServiceInstance -Identity "SERVER136" #Query Processing -  Index 1
$hostC = Get-SPEnterpriseSearchServiceInstance -Identity "SERVER137" #Query Processing -  Index 2

$hostD = Get-SPEnterpriseSearchServiceInstance -Identity “SERVER138" #Analytics Processing - Index 2 (Replica)
$hostE = Get-SPEnterpriseSearchServiceInstance -Identity “SERVER139” #Analytics Processing - Index 1 (Replica)
$hostF = Get-SPEnterpriseSearchServiceInstance -Identity “SERVER140" #Index 0 (Replica)

$hostG = Get-SPEnterpriseSearchServiceInstance -Identity “SERVER141" #Content Processing - Crawl Component
$hostH = Get-SPEnterpriseSearchServiceInstance -Identity “SERVER142" #Content Processing - Crawl Component

Next Step is to Start the Enterprise Search Service Instance on these servers

Start-SPEnterpriseSearchServiceInstance -Identity $hostA
Start-SPEnterpriseSearchServiceInstance -Identity $hostB
Start-SPEnterpriseSearchServiceInstance -Identity $hostC
Start-SPEnterpriseSearchServiceInstance -Identity $hostD
Start-SPEnterpriseSearchServiceInstance -Identity $hostE
Start-SPEnterpriseSearchServiceInstance -Identity $hostF
Start-SPEnterpriseSearchServiceInstance -Identity $hostG
Start-SPEnterpriseSearchServiceInstance -Identity $hostH

Now wait for all services to be provisioned.  You can check the status using the script below

//Wait until status of “OnLine” by issuing the following commands:

Get-SPEnterpriseSearchServiceInstance -Identity $hostA | Select Server, Status
Get-SPEnterpriseSearchServiceInstance -Identity $hostB | Select Server, Status
Get-SPEnterpriseSearchServiceInstance -Identity $hostC | Select Server, Status
Get-SPEnterpriseSearchServiceInstance -Identity $hostD | Select Server, Status
Get-SPEnterpriseSearchServiceInstance -Identity $hostE | Select Server, Status
Get-SPEnterpriseSearchServiceInstance -Identity $hostF | Select Server, Status
Get-SPEnterpriseSearchServiceInstance -Identity $hostG | Select Server, Status
Get-SPEnterpriseSearchServiceInstance -Identity $hostH | Select Server, Status

Now Next Step is to Get the Search Service Application and Create a new Search Topology.  To reuse existing topology you can clone it.

$ssa = Get-SPEnterpriseSearchServiceApplication
$newTopology  = New-SPEnterpriseSearchTopology -SearchApplication $ssa

Next Step would be to Create the Components.  Below i am creating by the hosts for easier managment.

Host A

New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostA
New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostA -IndexPartition 0

Host B

New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostB
New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostB -IndexPartition 1

Host C

New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostC
New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostC -IndexPartition 2

Host D

New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostD
New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostD -IndexPartition 2

Host E

New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostE
New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostE -IndexPartition 1

Host F

New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostF -IndexPartition 0
New-SPEnterpriseSearchAdminComponent -SearchTopology $newTopology -SearchServiceInstance $hostF

Host G

New-SPEnterpriseSearchCrawlComponent -SearchTopology $newTopology -SearchServiceInstance $hostG
New-SPEnterpriseSearchContentProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostG

Host H

New-SPEnterpriseSearchCrawlComponent -SearchTopology $newTopology -SearchServiceInstance $hostH
New-SPEnterpriseSearchContentProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostH

Now Set the topology as Active Topolgy

Set-SPEnterpriseSearchTopology -Identity $newTopology
iisreset 
Get-SPEnterpriseSearchTopology -SearchApplication $ssa

Remove the Old Toplogy

#Removing Old Topology Get-SPEnterpriseSearchTopology -SearchApplication $ssa #Note the ID of the old toplogy $OldTopology = Get-SPEnterpriseSearchTopology -SearchApplication $ssa -Identity 64e1b2ba-bfc6-44d4-9ebe-9f9b5952bdd0 #To Verify $OldTopology Remove-SPEnterpriseSearchTopology -Identity $OldTopology.Id -SearchApplication $ssa

#You are all Set now Open Central Administration –> Manage Service Applications –> Search #Service Application –> Review the components and all should show
#Green check mark. Refresh the browse if they take time to get green

Exporting SharePoint document using powershell


Few months back I found this PowerShell script and extended it to support a site collection.

$ver = $host | select version 
if($Ver.version.major -gt 1) {$Host.Runspace.ThreadOptions = "ReuseThread"} 
if(!(Get-PSSnapin Microsoft.SharePoint.PowerShell -ea 0)) 
{ 
Add-PSSnapin Microsoft.SharePoint.PowerShell  -ErrorAction SilentlyContinue
} 


$Directory = "c:\ExportFiles\" 
 
## 
#Define Functions 
## 
 
Function TrimDirectory ($Directory) 
{ 
    if($Directory.EndsWith("\")) 
    { 
        Set-Variable -Name Directory -Value ($Directory.Substring(0, ($Directory.Length -1))) -Scope Script 
    } 
} 
 
Function EnsureDirectory ($Directory) 
{ 
    if(!(Test-Path $Directory)) 
    { 
        TrimDirectory $Directory 
                 
        New-Item -Path $Directory -ItemType Directory 
    } 
} 
 
Function ExportFiles ($SPList, $GalleryName) 
{ 
    EnsureDirectory ($Directory + "\" + $GalleryName) 
    Write-Host $SPlist.rootfolder.files.count
    foreach ($file in $SPlist.rootfolder.files) 
    { 
         
        $DestinationFile = ($Directory + "\$GalleryName\" + $file.name) 
        $FileBinary = $file.OpenBinary() 
        $FileStream = New-Object System.IO.FileStream($DestinationFile), Create 
        $Writer = New-Object System.IO.BinaryWriter($FileStream) 
        $Writer.write($FileBinary) 
        $Writer.close() 
    } 
     
    foreach($Folder in $SPList.Folders) 
    { 
         
        if($ParentFolderURL) 
        { 
            Remove-Variable ParentFolderURL 
        } 
     
        $i = 0 
     
        $folderURL = $Folder.url.split("/") 
     
        while($I -lt ($FolderURL.count -1)) 
        { 
            $ParentFolderURL = "$ParentFolderURL/" + $FolderURL[$I] 
            $I++ 
        } 
         
        $DownloadDirectory = ($Directory + "\$GalleryName\" + $Folder.url.substring($SPList.RootFolder.Url.Length)) -replace "/", "\" 
         
        EnsureDirectory $DownloadDirectory 
         
        foreach ($File in $Folder.Folder.Files) 
        { 
            $DestinationFile = ($Directory + "\$GalleryName\" + $Folder.url.Substring($SPList.Rootfolder.URL.Length) + "\" + $file.name) -replace "/", "\" 
             
            $FileBinary = $file.OpenBinary() 
 
            $FileStream = New-Object System.IO.FileStream($DestinationFile), Create 
 
            $Writer = New-Object System.IO.BinaryWriter($FileStream) 
 
            $Writer.write($FileBinary) 
 
            $Writer.close() 
        } 
         
         
    } 
} 
 
 
## 
#Start Script 
## 
 
 
TrimDirectory $Directory 
EnsureDirectory $Directory 

Start-SPAssignment -Global

$SiteURL = "http://intranet.hp.com"
$Site = Get-SPSite $SiteURL

foreach($Web in $Site.AllWebs)
{

    foreach($List in $Web.Lists)
    {
        if(!$List.Hidden)
        {
            $Title = $List.Title
            Write-Host $Title
            $ListFolder = New-Item -Path ($Directory + "\$Title") -ItemType Directory -ErrorAction SilentlyContinue
            ExportFiles $List $Title.ToString()
        }
    }
}

Stop-SPAssignment -Global

#New-Item -Path ($Directory + "\Documents") -ItemType Directory 
#$Documents = $Site.RootWeb.Lists | ? {$_.title -eq "Documents"} 
#ExportFiles $Documents "Documents" 

Powershell – current folder and file


While working with PowerShell some times if is required to access resources like XML and csv files from local folder where the PS1 file is placed.  PowerShell 3.0 has made it easy for us.  Use the script below to get current folder, file and execution path

$thisfolderIncludingFileName = Split-Path -parent $MyInvocation.MyCommand.Definition
$currentScriptName = $MyInvocation.MyCommand.Name

$currentExecutionPath = $thisfolderIncludingFileName.Replace($currentScriptName, "");

Write-Host "Current Folder with FileName : $thisfolder"
Write-Host "Current File Name : $currentScriptName"
Write-Host "Current Exeuction Path $currentExecutionPath"

image

Note: I have find out that you must save your script file before you can test these calls and you can not get this path when you press F8 to execute any script line by line.