PropertyBag values in SharePoint 2013 can be indexed, which means that they’re indexed by Search and a crawled property is created using the PropertyBag name as the crawled property name. If you then create a managed property mapped to the crawled property you can use it in your search queries.
The code below creates an indexed propertybag value, On-Premises using the server API;
$web = Get-SPWeb "http://pub.pdogs.local" $web.AllProperties["MyPropertyName"] = "some value" $web.IndexedPropertyKeys.Add("MyPropertyName") $web.Update()
If you then run a search crawl, there will be a crawled property created called “MyPropertyName”.
For Office 365, the story is not so good as the ‘IndexPropertyKeys’ property is not present in the CSOM API. However, indexed property keys are added to another PropertyBag value called “vti_indexedpropertykeys“, which we can add the property bag keys we wish to index to.
The vti_indexedpropertykeys property has a special encoding in the form;
{Base64 encoding of the unicode bytes of the property name} followed by the pipe | character
E.g.
So, to set an ‘indexed’ propertybag value using CSOM we can use the following code (the code shown is PowerShell + CSOM)
function Set-PropertyBag { | |
param ( | |
[string]$PropertyName, | |
[string]$PropertyValue = $null, | |
[bool]$Indexable = $false, | |
[Microsoft.SharePoint.Client.Web]$Web, | |
[Microsoft.SharePoint.Client.ClientContext]$ClientContext | |
) | |
process { | |
$indexedPropertyBagKey = "vti_indexedpropertykeys" | |
if($Indexable) { | |
$ClientContext.Load($Web.AllProperties) | |
$ClientContext.ExecuteQuery() | |
$oldIndexedProperties = $Web.AllProperties.FieldValues[$indexedPropertyBagKey] | |
if($oldIndexedProperties -ne $null) { | |
$oldIndexedProperties = $oldIndexedProperties.ToString() | |
} else { | |
$oldIndexedProperties = "" | |
} | |
$propertyNameBytes = [System.Text.Encoding]::Unicode.GetBytes($PropertyName) | |
$encodedPropertyName = [Convert]::ToBase64String($propertyNameBytes) | |
if($oldIndexedProperties -notlike "*$encodedPropertyName*") { | |
$Web.AllProperties[$indexedPropertyBagKey] = "$oldIndexedProperties$encodedPropertyName|" | |
} | |
} | |
$Web.AllProperties[$PropertyName] = $PropertyValue | |
$Web.Update() | |
$ClientContext.Load($Web) | |
$ClientContext.Load($Web.AllProperties) | |
$ClientContext.ExecuteQuery() | |
} | |
} |
To test this out I created an indexed propertybag value called ‘MyWebTemplateID’
Then I ran a search crawl, and found the crawled property;
I created a new managed property (called propMyWebTemplateID) and mapped the above crawled property it, then ran another search crawl.
Then doing a search using the query below results in the site or sites which have this propertybag value;
(contentclass:STS_Web OR contentclass:STS_Site) propMyWebTemplateID:CorpNews
You can imagine a great many uses for this type of capability, not least of which is some kind of dynamic site map driven by search, tie this in with site provisioning where these types of propertybag values are added to sites as they are created, and you have quite a powerful site search feature.
Reblogged this on Dinesh Ram Kali..