In this article
In the first article , we saw how to create a search service application in SharePoint 2013 using PowerShell. In this article we will see how to configure search
Get the reference of the search service application and proxy
$searchApp = Get-SPEnterpriseSearchServiceApplication $SearchServiceAppName$searchAppProxy = Get-SPEnterpriseSearchServiceApplicationProxy $SearchServiceAppName
Remove the web application URL from the default content source
function RemoveWebAppUrlFromLocalSPSites {
$localSitesContentSource = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchApp -Identity "Local SharePoint Sites" -ErrorAction SilentlyContinue
if (-not $localSitesContentSource) {
Write-Host "Search Content Source 'Local SharePoint Sites' application not found"
return
}
else {
Write-Host "Checking if the current '$WebAppUrl' isn't part of the 'Local SharePoint Sites' Content Source"
if ($localSitesContentSource.StartAddresses.Exists($WebAppUrl)) {
Write-Host "Removing '$WebAppUrl' from the 'Local SharePoint Sites' Content Source"
$localSitesContentSource.StartAddresses.Remove($WebAppUrl)
$localSitesContentSource.Update()
}
}
}
RemoveWebAppUrlFromLocalSPSites
Create the content source and configure the incremental and full crawl
function CreateContentSource {
param ($Name)
$created = $false
Write-Host "Check if '$Name' Content Source exists"
$contentSource = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchApp -Identity $Name -ErrorAction SilentlyContinue
if (-not $contentSource) {
Write-Host "Creating '$Name' Content Source"
$contentSource = New-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchApp -Name $Name -Type SharePoint -StartAddresses $SiteUrl -SharePointCrawlBehavior CrawlSites
$created = $true
}
Write-Host 'Configure incremental search'
$context=[Microsoft.Office.Server.Search.Administration.SearchContext]::GetContext($SearchServiceAppName)
$incremental=New-Object Microsoft.Office.Server.Search.Administration.DailySchedule($context)
$incremental.StartHour="7";
$incremental.DaysInterval="1";
$incremental.RepeatInterval="15";
$incremental.RepeatDuration="1080";
Write-Host 'Configure full crawl'
$fullCrawl=New-Object Microsoft.Office.Server.Search.Administration.DailySchedule($context)
$fullCrawl.StartHour="4";
$fullCrawl.DaysInterval="1";
$contentSource.IncrementalCrawlSchedule=$incremental
$contentSource.FullCrawlSchedule=$fullCrawl
$contentSource.Update()
if ($created) {
# if the search was just created first do a full crawl to ensure managed properties are avaible
Write-Host "Starting full crawl for content source $($contentSource.Name)..."
$contentSource.StartFullCrawl()
do {
Start-Sleep -Seconds 2
Write-Host '.' -NoNewLine
}
while ($contentSource.CrawlStatus -ne "Idle")
write-host "`n"
}
}
CreateContentSource -Name 'TestContentSource'
Create the custom managed property from the crawled property
function ConfigureMetadataProperty {
param ($Name, $MetadataPropertyType)
Write-Host "Check if '$Name' managed property exists - if not, create and configure"
$managedProp = Get-SPEnterpriseSearchMetadataManagedProperty -SearchApplication $searchApp -Identity $Name -ErrorAction SilentlyContinue
if (-not $managedProp) {
Write-Host "Creating '$Name' managed property"
$managedProp = New-SPEnterpriseSearchMetadataManagedProperty -Name $Name -SearchApplication $searchApp -Type $MetadataPropertyType | Out-Null
# get the managedProp again, it sometimes is NULL after New-SPEnterpriseSearchMetadataManagedProperty
$managedProp = Get-SPEnterpriseSearchMetadataManagedProperty -SearchApplication $searchApp -Identity $Name
}
Write-Host "Configure'$Name' managed property"
$managedProp.MaxCharactersInPropertyStoreIndex = "2048000"
$managedProp.MaxCharactersInPropertyStoreForRetrieval = "2048000"
$managedProp.EnabledForScoping = $true
$managedProp.Update()
return $managedProp
}
function CreateManagedProperty {
param ($Name, $CrawledProperty, $MetadataPropertyType)
$managedProp = ConfigureMetadataProperty -Name $Name -MetadataPropertyType $MetadataPropertyType
$managedMapping = Get-SPEnterpriseSearchMetadataMapping -SearchApplication $searchapp -ManagedProperty $managedProp
if (-not $managedMapping -or $managedMapping .CrawledPropertyName -ne $CrawledProperty) {
Write-Host "Creating mapping for '$Name' managed property"
$category = Get-SPEnterpriseSearchMetadataCategory -Identity SharePoint -SearchApplication $searchapp
$crawledContenttypeProperty = Get-SPEnterpriseSearchMetadataCrawledProperty -SearchApplication $searchapp -Category $category -Name $CrawledProperty
New-SPEnterpriseSearchMetadataMapping -SearchApplication $searchapp -ManagedProperty $managedProp -CrawledProperty $crawledContenttypeProperty | Out-Null
}
}
CreateManagedProperty -Name 'CustomManagedProperty' -CrawledProperty 'CrawledProperty' -MetadataPropertyType 1
Update the existing managed property to refer to the crawled property
function UpdateManagedProperty {
param ($Name, $CrawledProperty,$SearchApp)
Write-Host "Fetch the managed metadata mapping for $Name"
$managedProperty = Get-SPEnterpriseSearchMetadataManagedProperty -SearchApplication $SearchApp -Identity $Name
$managedProperty.MappingsOverridden = $true
$managedProperty.DeleteAllMappings()
$managedProperty.Update()
$category = Get-SPEnterpriseSearchMetadataCategory -SearchApplication $SearchApp
$cat =$category |?{$_.Name -eq "Sharepoint"}
$crawledContenttypeProperty = Get-SPEnterpriseSearchMetadataCrawledProperty -SearchApplication $SearchApp -category $cat -Name $CrawledProperty
$result = $managedProperty.GetMappings() |? { $_.CrawledPropertyName -eq $CrawledProperty}
if($result -eq $null)
{
Write-Host "Creating the managed mapping for $Name"
$map = New-SPEnterpriseSearchMetadataMapping -SearchApplication $SearchApp -ManagedProperty $managedProperty -CrawledProperty $crawledContenttypeProperty
}
}
UpdateManagedProperty -Name 'ExistingManagedProperty' -CrawledProperty 'NewCrawledProperty' -SearchApp $searchApp
$contentSource = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $searchApp -Identity 'TestContentSource' -ErrorAction SilentlyContinue
$contentSource.StartFullCrawl()
do {
Start-Sleep -Seconds 2
Write-Host '.' -NoNewLine
}
while ($contentSource.CrawlStatus -ne "Idle")
Create result source
function CreateResultSource {
param
(
$ScopeName,$SiteUrl,$SearchOwner,$FederationManager
)
$searchQuery = "?{searchTerms} "+("ContentSource=TestContentSource (Path:{0}) AND (-ManagedProperty:Value) OR (ManagedProperty1:Value2)" -f $siteURL)
# create result source
$resultSource = $federationManager.CreateSource($SearchOwner)
$resultSource.Name = $ScopeName
$resultSource.ProviderId = $FederationManager.ListProviders()['Local SharePoint Provider'].Id
$resultSource.CreateQueryTransform($searchQuery)
$resultSource.Commit()
Write-Host "Created search result source $ScopeName"
}
$site = Get-SPSite $SiteUrl
[void] [Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.Search")
$federationManager = New-Object Microsoft.Office.Server.Search.Administration.Query.FederationManager($searchApp)
$searchOwner = New-Object Microsoft.Office.Server.Search.Administration.SearchObjectOwner([Microsoft.Office.Server.Search.Administration.SearchObjectLevel]::SPSite, $site.RootWeb)
if($federationManager.GetSourceByName("TestResultSource", $searchOwner) -eq $null)
{
CreateResultSource -ScopeName 'TestResultSource' -SiteUrl $SiteUrl -SearchOwner $searchOwner -FederationManager $federationManager | Out-Null
}
else
{
Write-Host "The search result source 'TestResultSource' already exists"
}
Create result type
function CreateResultType {
param ($Name, $ResultSource,$ItemTemplateURL,$SiteUrl, $SearchApp)
$web = Get-SPWeb $SiteUrl
$tenantOwner = Get-SPEnterpriseSearchOwner -Level SPSite -SPWeb $web
$resultType = Get-SPEnterpriseSearchResultItemType -Owner $tenantOwner -SearchApplication $SearchApp |? { $_.Name -eq $Name }
if($resultType -eq $null){
Write-Host "Creating result type $Name."
$svcAppProxy = Get-SPEnterpriseSearchServiceApplicationProxy
$ssa = Get-SPEnterpriseSearchServiceApplication $searchApp
$displayProperties = "WorkId,Rank,Title,Size,Path,Description,SiteName,HitHighlightedSummary,HitHighlightedProperties,ViewsLifeTime,CustomManagedProperty"
$ruleCollection = Get-SPEnterpriseSearchPropertyRuleCollection
$resultSource = Get-SPEnterpriseSearchResultSource -Identity $ResultSource -SearchApplication $ssa -Owner $tenantOwner
New-SPEnterpriseSearchResultItemType -SearchApplicationProxy $svcAppProxy -Name $Name -Rules $ruleCollection -RulePriority 1 -DisplayProperties $displayProperties -DisplayTemplateUrl $ItemTemplateURL -Owner $tenantOwner -SourceID $resultSource.Id | Out-Null
Write-Host "Successfully created result type $Name."
}
else{
Write-Host "Result type $Name already exists."
}
}
$displayTemplateUrl = "~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Custom.js"
CreateResultType -Name 'TestResultType' -ResultSource "TestResultSource" -ItemTemplateURL $displayTemplateUrl -SiteUrl $SiteUrl -SearchApp $searchApp
Create query rules as best bet
function CreateQueryRules {
param
(
$SiteUrl,$Name,$Synonyms,$LinkTitle,$LinkDescription,$LinkUrl
)
$searchServiceApplication = Get-SPEnterpriseSearchServiceApplication -ErrorAction SilentlyContinue
if($searchServiceApplication -ne $null)
{
$site = Get-SPSite $SiteUrl
$searchOwner = New-Object Microsoft.Office.Server.Search.Administration.SearchObjectOwner -ArgumentList @([Microsoft.Office.Server.Search.Administration.SearchObjectLevel]::SPSite,$site.RootWeb)
$searchObjectFilter = New-Object Microsoft.Office.Server.Search.Administration.SearchObjectFilter($searchOwner)
$queryRuleManager = New-Object Microsoft.Office.Server.Search.Query.Rules.QueryRuleManager($searchServiceApplication)
$queryRules = $queryRuleManager.GetQueryRules($searchObjectFilter)
if($queryRules.DisplayName -notcontains $LinkTitle)
{
Write-Host "Creating Query Rule $LinkTitle"
$queryRule = $queryRules.CreateQueryRule($LinkTitle,$null,$null,$true)
[string[]]$keywords = $Name
foreach ($synonym in $Synonyms) {
if (-not [String]::IsNullOrEmpty($synonym)) {
$keywords+= $synonym
}
}
$keywordCondition = $queryRule.QueryConditions.CreateKeywordCondition($keywords,$false)
$queryAction = $queryRule.CreateQueryAction([Microsoft.Office.Server.Search.Query.Rules.QueryActionType]::AssignBestBet)
$promotedResultCollection = $searchServiceApplication.GetBestBets($searchObjectFilter)
$promotedResult = $promotedResultCollection.CreateBestBet($LinkTitle, $LinkUrl, $LinkDescription, $false)
$queryAction.BestBetIds.Add($promotedResult.Id);
$queryRule.Update()
$searchServiceApplication.Update()
Write-Host "Created Promoted Result for" $LinkTitle
}
else
{
Write-Host "The search query rule $LinkTitle already exists"
}
}
}
CreateQueryRules -SiteUrl $SiteUrl -Name 'BestBetKeyword' -Synonyms ('Synonym1','Synonym2','Synonym3') -LinkTitle 'Title' -LinkDescription 'Description' -LinkUrl "$($SiteUrl)"