Setup Sharepoint Search by Powershell

18/01/2013 17:13

#Search Settings

$searchAppName="Search Service Application"
$hostsPath="C:\Windows\System32\drivers\etc\hosts"

$scopeName="LukasScope"
$scopeDescription="Lukas custom scope"

#where to search (relative path)
$searchLbraryUrl="/Pages"

#which Content Type Should be filtered
$searchContentTypeName="Lukas custom Page"


#======================= input variables ===========================================
#Set Site collection Url

    $siteUrl="https://server/sitecollection"

#========================= end of input variables ==================================

 #1. Check if web application host header is in content source
 #2. Check if web application is written in host file
 #3. Check 'Ignore SSL warnings' for Search Service
 #4. Check if 'ContentType' property is allowed for scopes
 #5. Creating search scope with rules
 #6. Search Index Reset and start full crawl
 #7. Creating managed properties and mapping
 #8. Site Collection Search Setting: Do not use custom scopes
 #9. Todo: Update scopes, run timer job
 #10. Start Full Crawl again
 
write-host ""
write-host "=========================== starting 11.SearchConfiguration.ps1 =============================="
Write-Host ""
Start-SPAssignment -Global
#$answer = Read-Host "Do you want to run 'Search Configuration' for" $siteUrl "? [y/n]"
#if($answer -ne "y")
#{
# Write-Host "Search Configuration aborted."
# break;
#}

#set default search service application name, you have to select if they are more
 if([string]::IsNullOrEmpty($searchAppName))
 {
     $searchapp = Get-SPEnterpriseSearchServiceApplication
     $searchapp = SelectChoice -option $searchapp
     write-host "You have chosen " $searchapp.Name
     $searchAppName=$searchapp.Name
 }
 else
 {
 $searchapp = Get-SPEnterpriseSearchServiceApplication $searchAppName
 }
 
 #Get Web application url for SPSite object
 $site = Get-SPSite $siteUrl
 $webAppUrl = RemoveLastSlashFromUrl $site.WebApplication.Url #"https://Chamdev7.Cham.gmd.lab"
 
 #1. Check if web application name is present in Content Sources
 
  Write-Host "1. Checking if web application name is present in Content Sources..."
  $contentSources = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchAppName
  $wasFound=$false
  $contentSourceForCrawl=$null
  foreach($cs in $contentSources)
  {
   $conSource = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchAppName -Identity $cs.Name
   $found = $conSource.StartAddresses |Where-Object {$_.OriginalString  -eq $webAppUrl}
  if($found -ne $null)
  {
   $wasFound=$true
   $contentSourceForCrawl=$conSource
   break;
  }
  }
  if($wasFound)
  {
   Write-Host "Web application $webAppUrl is present in content sources."
  }
  else
  {
   Write-Host "Web application $webAppUrl is not in content sources. Adding..."
  $mainContentSource = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchAppName -Identity "Local Sharepoint Sites"
  $mainContentSource.StartAddresses.Add($webAppUrl)
  $contentSourceForCrawl=$mainContentSource
  Write-Host "Web application $webAppUrl was added to 'Local Sharepoint Sites' content source."
  }

#2. Check if web application is written in host file

 Write-Host "2.Check if web application is written in hosts file..."
 $rootSiteUrlWithoutProtocol = $webAppUrl.split('/')[2]
 $foundHost = Select-String -path $hostsPath -pattern $rootSiteUrlWithoutProtocol
    if($foundHost -eq $null)
    {
        Add-Content -Path $hostsPath -Value ("`r`n127.0.0.1          " + $rootSiteUrlWithoutProtocol )
        Write-Host $rootSiteUrlWithoutProtocol " succesfuly added to " $hostsPath
    }
    else
    {
        Write-Host $rootSiteUrlWithoutProtocol " is already present in " $hostsPath
    }

#3. Check 'Ignore SSL warnings' for Search Service

 $searchService = Get-SPEnterpriseSearchService
 if($searchService.IgnoreSSLWarnings -eq $false)
 {
  Write-Host "3. Setting Ignore SSL Warnings to true..." -NoNewline
  $searchService.IgnoreSSLWarnings = $true
  Write-Host "OK"
 }


#4. Check if 'ContentType' property is allowed for scopes

 write-host "4. Checking 'ContentType' property is Enabled for scopes: " -NoNewline
 $ctProperty = Get-SPEnterpriseSearchMetadataManagedProperty -SearchApplication $searchapp -Identity "ContentType"
 if($ctProperty.EnabledForScoping -eq $false)
 {
  $ctProperty.EnabledForScoping = $true;
  $ctProperty.Update();
 }
 Write-Host "OK"
 
#5. Creating search scope with rules
 write-host "5. Creating search scope with rules... "
 $category = Get-SPEnterpriseSearchMetadataCategory –Identity SharePoint -SearchApplication $searchapp
 if($category.AutoCreateNewManagedProperties -eq $false)
 {
  $category.AutoCreateNewManagedProperties=$true
  $category.Update()
 }
 
 
 #if scope exists, delete and create new
 $scope = Get-SPEnterpriseSearchQueryScope -Identity $scopeName -SearchApplication $searchapp -ea 0
 
 if($scope -ne $null) #if scope exists, delete
     {
      write-host $scopeName " scope already exist in " $searchAppName ", deleting..."
      Remove-SPEnterpriseSearchQueryScope -Identity $scopeName -SearchApplication $searchapp -Confirm:$false
      write-host $scopeName " scope has been successfuly removed from " $searchAppName "."
     }

 #Scope doesn't exis, create
 write-host $scopeName " scope doesn't exist in " $searchAppName ", creating..."
 $searchapp | New-SPEnterpriseSearchQueryScope -Name $scopeName -Description $scopeDescription -DisplayInAdminUI $true|out-null
 $scope = Get-SPEnterpriseSearchQueryScope -Identity $scopeName -SearchApplication $searchapp
 
 #Add Rules
 $scopeUrl=$siteUrl + $searchLbraryUrl
 $scopeRule = New-SPEnterpriseSearchQueryScopeRule  -RuleType Url -MatchingString $scopeUrl -UrlScopeRuleType "Folder" -FilterBehavior "Require" -Url $siteUrl -Scope $scope
 $scopeRule = New-SPEnterpriseSearchQueryScopeRule -RuleType PropertyQuery -ManagedProperty "ContentType" -PropertyValue $searchContentTypeName -FilterBehavior "Require" -url $siteUrl -scope $scope -SearchApplication $searchapp
 #Examples:
 #$scopeRule = New-SPEnterpriseSearchQueryScopeRule -RuleType PropertyQuery -ManagedProperty "ContentType" -PropertyValue "Lucas Custom Page" -FilterBehavior Include -url "https://server/sitecollection/Pages" -scope $scope -SearchApplication $searchapp
 #$scopeRule = New-SPEnterpriseSearchQueryScopeRule  -RuleType Url -MatchingString "https://server/sitecollection/Pages" -UrlScopeRuleType "Folder" -FilterBehavior "Include" -Url "https://server/sitecollection/Pages" -Scope $scope
       
    write-host $scopeName " scope has been successfuly created in " $searchAppName "."

#6. Search Index Reset and start full crawl

 #Reset index with the following options in brackets:
 #Disable Alerts $true/$false
 #Ignore unreachable server $true/$false
 write-host "6. Search Index Reset and start full crawl...This may take several minutes. "
 try
 {
     Write-Host "Attempting to reset the index...please wait"
     $searchapp.Reset($false, $false)
     Write-Host "Index successfully reset"
 }
 catch
 {
     Write-Host "There was a problem resetting the index:" $_ -ForegroundColor Red
 }
 
 #Start full crawl
 Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchAppName | select Name, CrawlStatus
 StartFullCrawlForContentSource -contentSource $contentSourceForCrawl

#7. Creating managed properties and mapping

 write-host "7. Creating managed properties and mapping...: "
 #if managed properties already exists, they are removed
 #NOTE: Type 4 is managed property type 'DateTime' from enum: 'Text', 'Integer', 'Decimal', 'DateTime'
 CreateManagedProperty -searchapp $searchapp -managedPropertyName "owsChamLukasArticleDate" -crawledpropertyName "ows_ChamLukasArticleDate" -variantType 64 -type 4
 CreateManagedProperty -searchapp $searchapp -managedPropertyName "PublishingPageContent" -crawledpropertyName "ows_PublishingPageContent" -variantType 31 -type 1
 CreateManagedProperty -searchapp $searchapp -managedPropertyName "owsChamLukasCategory" -crawledpropertyName "ows_ChamLukasCategory" -hasMultipleValues $true -variantType 31 -type 1
 CreateManagedProperty -searchapp $searchapp -managedPropertyName "owsChamLukasTags" -crawledpropertyName "ows_ChamLukasTags" -hasMultipleValues $true -variantType 31 -type 1
 CreateManagedProperty -searchapp $searchapp -managedPropertyName "owsChamLukasIntroductionText" -crawledpropertyName "ows_ChamLukasIntroductionText" -variantType 31 -type 1
 CreateManagedProperty -searchapp $searchapp -managedPropertyName "owsChamLukasAuthor" -crawledpropertyName "ows_ChamLukasAuthor" -variantType 31 -type 1

#8. Site Collection Search Setting: Do not use custom scopes

 write-host "8. Site Collection Search Setting: Do not use custom scopes: " -NoNewline
 $web = get-spweb $webUrl
 $web.AllowUnsafeUpdates = $true
 $web.AllProperties["SRCH_ENH_FTR_URL"]=$null
 $web.update()
 write-host "OK"


#9. Update scopes

 write-host "9. Updating scopes...: " -NoNewline
 Update-Scopes($siteUrl)
 write-host "OK"
 
 
#10. Start Full Crawl again

 StartFullCrawlForContentSource -contentSource $contentSourceForCrawl
 
 Write-Host "Search setting completed."
  Stop-SPAssignment -Global
 
 
 

#Functions in sampleFunctions.ps1, include it or copy code to the same file.

# StartFullCrawlForContentSource

# StartFullCrawl

# RemoveLastSlashFromUrl

# Update-Scopes

# CreateManagedProperty

# SelectChoice

 

function StartFullCrawlForContentSource
{
    param([object]$contentSource)
 
 Write-Host "Crawling content source: " $contentSource.Name
 $contentSource.CrawlStatus
 if ($contentSource.CrawlStatus  -eq "Idle")
    {
        $contentSource.StartFullCrawl()
    }
 $contentSource.CrawlStatus   
 while ($contentSource.CrawlStatus -ne "Idle")
 {
     start-sleep -s 10 #wait one minute
     write-host $contentSource.CrawlStatus
 }
 write-host "Full crawl finished."
}
function StartFullCrawl
{
    param([string]$searchAppName)

 $searchapp = Get-SPEnterpriseSearchServiceApplication $searchAppName
 $CrawlContent = Get-SPEnterpriseSearchServiceApplication $searchapp| Get-SPEnterpriseSearchCrawlContentSource
 foreach($contentSource in $CrawlContent)
 {
  if ( $contentSource.CrawlStatus  -eq "Idle" )
      {
          $contentSource.StartFullCrawl()
      }
     
  $contentSource.CrawlStatus   
  while ($contentSource.CrawlStatus -ne "Idle")
  {
      start-sleep -s 10 #wait one minute
      write-host $contentSource.CrawlStatus
  }
  write-host "Full crawl finished."
 }
}

function RemoveLastSlashFromUrl($url)
{
 if($url.LastIndexOf("/")+1 -eq $url.Length)
 {
  $newUrl=$url.substring(0, $url.length -1)
 }
 else
 {
  $newUrl = $url
 }
 return $newUrl
}


function Update-Scopes($siteUrl)
{
 [void][reflection.assembly]::Loadwithpartialname("Microsoft.SharePoint") | out-null
 [void][reflection.assembly]::Loadwithpartialname("Microsoft.office.server.search") | out-null
 
 $s = [microsoft.sharepoint.spsite]$siteUrl
 $sc = [microsoft.office.server.servercontext]::GetContext($s)
 $search = [Microsoft.Office.Server.Search.Administration.SearchContext]::GetContext($sc)
 $scopes = [microsoft.office.server.search.administration.scopes]$search
 $scopes.StartCompilation()
 while ($scopes.CompilationPercentComplete -lt 100) { sleep -seconds 3; write-host "$($scopes.CompilationPercentComplete)% complete" }
}

function CreateManagedProperty
 {
     param(
         [object]$searchapp,
         [String]$managedPropertyName,
         [String]$crawledPropertyName,
   [bool]$hasMultipleValues,
   [int]$variantType,
   [int]$type
          )
 
  #set default value for search application
  if($searchapp -eq $null)
  {
      $searchapp = Get-SPEnterpriseSearchServiceApplication 'Enterprise Search Service Application'
  }
  
  $category="Sharepoint"
  
   $crawledproperty = New-SPEnterpriseSearchMetadataCrawledProperty -SearchApplication $searchapp -Category $category -VariantType $variantType -PropSet "00130329-0000-0130-c000-000000131346" -Name $crawledPropertyName -IsNameEnum $false
  $managedproperty = Get-SPEnterpriseSearchMetadataManagedProperty -SearchApplication $searchapp -Identity $managedPropertyName -ea 0

  if($managedproperty -ne $null) #if managed property exists, remove it
  {
  Write-Host "Deleting property  $managedPropertyName ..."
     $managedproperty.DeleteAllMappings()
     $managedproperty.Delete()
  }
  #managed property doesn't exist, create
  Write-Host "Creating property  $managedPropertyName ..."
  
     $managedproperty = New-SPEnterpriseSearchMetadataManagedProperty -SearchApplication $searchapp -Name $managedPropertyName -Type $type -EnabledForScoping 1
  if($hasMultipleValues)
  {
   $managedproperty.HasMultipleValues = $hasMultipleValues
  }
  $managedproperty.Update()
  Write-Host ""
     New-SPEnterpriseSearchMetadataMapping -SearchApplication $searchapp -ManagedProperty $managedproperty -CrawledProperty $crawledproperty
 } 
 

#if input parameter is collection, function enables choice
function SelectChoice
 {
         param(
         [array]$options
         )


 if(($options.length -gt 1))
     {
         write-host "======================================================="
         write-host "There are more options of parameter, choose the number."
         write-host "======================================================="
         for($i=0; $i -le $options.length-1; $i++)
             {
                 write-host ($i+1) ". " $options[$i]
             }
         $index=read-host "Select the option number."
         #write-host "You selected number "$index " with value " $options[$index-1]
         $result=$options[$index-1]
         return $result
   
     }
  else
  {
     #write-host "They are no choices, only this one value: "$options[0]
     $result=$options[0]
     return $result
  }  
 }