6

The title pretty much says it all - I've looked at the docs but I just keep finding Get-Item and Get-ItemTempate.

Lets say I have a template with id 123456, I want to get all items that are using this template. How would I do that?

  • How would you do that in C#? – Alan Płócieniak Nov 26 '18 at 15:25
  • Something like allItems.Where(p => p.TemplateIdList.Contains("123456")); Let me see if I can powershell that! - Disclaimer - New to Sitecore so I don't know what exists and what doesn't... – Percy Nov 26 '18 at 15:33
7

This should do it for you.

$defaultPath = "/sitecore/content"
[Sitecore.Data.ID]$articleId = "{03360FC1-B4C0-4770-9E1D-79E8317B74DD}"

$articles = Find-Item -Index sitecore_master_index `
   -Where 'TemplateId = @0 and Path.StartsWith(@1)' `
   -WhereValues $articleId, $defaultPath | Initialize-Item

Another way using template name and Criteria.

$articles = Find-Item `
   -Index sitecore_master_index `
   -Criteria @{Filter = "Equals"; Field = "_templatename"; Value = "Article"},
   @{Filter = "Equals"; Field = "_language"; Value = "en"},
   @{Filter = "StartsWith"; Field = "_fullpath"; Value = "/sitecore/content" } 
  • If I do a Write-Host $_.FullPath on everything in $articles, then I get quite a log of duplicates. Any idea why this would happen? – Percy Nov 26 '18 at 16:52
  • (using the first example btw) – Percy Nov 26 '18 at 17:08
  • multiple languages? This is is reading directly from the index, so we have to know why there are multiple items in your index. – Chris Auer Nov 26 '18 at 17:18
  • 1
    Ah potentially - I'll investigate if that is the case. Thanks – Percy Nov 26 '18 at 17:18
7

There is a report included with SPE called Items with Template that can provide you with this information. This report scans a tree and checks for inheritance at any level. Slow because it has to look at every item. Incomplete because it only looks at the tree specified.

Sample Report Dialog

I would recommend you use the Get-ItemReferrer command. This is based on the Link Database and should be extremely fast; items that in no way are related are never requested. Be sure the Link Db is up-to-date before running.

A similar question was asked here.

Find related items

Example: The following returns all items referring to a given template.

$sampleItemTemplateId = "{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"
$sampleItemTemplateItem = Get-Item -Path "master:" -ID $sampleItemTemplateId

Get-ItemReferrer -Item $sampleItemTemplateItem

As you can see below, all referrers are returned. You can then filter out with Where-Object if you want to exclude content, media, templates, etc.

enter image description here

Find related items at any level of inheritance

Example: The following returns all items referring to a given template that inherit that template. Demonstrates the use of the trampoline technique to reduce call depth. There are checks to ensure that the item exists and no duplicates are returned.

function Get-ItemBasedOnTemplate {
    param(
        [string]$TemplateId
    )

    $queue = New-Object System.Collections.Queue
    $processedLookup = New-Object System.Collections.Generic.HashSet[string]
    if(-not(Test-Path -Path "master:$($TemplateId)")) { return }
    $processedLookup.Add($TemplateId) > $null  
    Get-ItemReferrer -Id $TemplateId -ItemLink | 
        Where-Object { $_.SourceItemID } | 
        ForEach-Object { $queue.Enqueue($_.SourceItemID) }

    $database = Get-Database -Name "master"
    while($queue.Count -and ($referrerId = $queue.Dequeue())) {
        if($processedLookup.Contains($referrerId)) { continue }
        $processedLookup.Add($referrerId) > $null
        $referrer = $database.GetItem($referrerId)
        if(!$referrer) { continue }
        if($referrer.Paths.FullPath.StartsWith("/sitecore/templates")) { 
            if($referrer.Name -eq "__Standard values") { continue }
            foreach($referrerItemLink in Get-ItemReferrer -Id $referrerId -ItemLink | Where-Object { $_.SourceItemID }) {
                $queue.Enqueue($referrerItemLink.SourceItemID)
            }
            $itemTemplate = [Sitecore.Data.Managers.TemplateManager]::GetTemplate($referrerId, $database)
        } else {
            $itemTemplate = [Sitecore.Data.Managers.TemplateManager]::GetTemplate($referrer)
        }

        if ($itemTemplate -and $itemTemplate.DescendsFromOrEquals($TemplateId)) {
            $referrer
        }
    }
}
$baseTemplateId = "{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"
Get-ItemBasedOnTemplate -TemplateId $baseTemplateId

Demo

The following demonstrates three base templates: Base Template -> Base Template 1 -> Base Template 2

Query base template

Interesting discovery. Switched from Get-Item to $db.GetItem() and the results are considerably faster; SPE wraps objects returned Get-Item and Get-ChildItem with additional properties.

$baseTemplateId = "{3F8A6A5D-7B1A-4566-8CD4-0A50F3030BD8}"
$watch = [System.Diagnostics.Stopwatch]::StartNew()
$itemCount = Get-ItemBasedOnTemplate -TemplateId $baseTemplateId | 
    Measure-Object | Select-Object -Expand Count
$watch.Stop()
$time = $watch.ElapsedMilliseconds / 1000
Write-Host "Discovered and returned $($itemCount) items in $($time) seconds"

# Discovered and returned 1307 items in 0.527 seconds
  • Nice one Mike. Didn't know that existed. – Chris Auer Nov 26 '18 at 17:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.