Setup Sharepoint Search by Powershell
#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
}
}