Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
Experience Sitecore! | All posts tagged 'Buckets'

Experience Sitecore!

Martin Miles on Sitecore

Understanding Buckets: adding new items to buckets correctly

I just came across a question on StackOverflow about Buckets, so I decided to highlight in my blog, as it it is based on very common misunderstanding of Buckets and their functioning principles. Here's the link to original SO question.

If briefly, a guy asked why having a bucket folder with several items in it, when he tries to add a new item, the one appears in a folder as normal item, not hidden. So every time he adds new item he has to perform Sync on that. So let's go and reproduce the situation by steps.

Prerequisites: I have a folder with some items that I am turning into a bucket (at that stage we assume those Articles 1 - 5 have Bucketable checkbox being set on individual level; if you don't know how to update a checkbox for multiple already existing items - here is the great blog post about mass update field values I wrote about):


At this stage my folder is a bucket, items are not displayed, but are searchable, everything functions as normal.



The issue: Then I try to add a new item called Article 6 into my bucket folder. That item is being created as normal, is diaplyed within a folder, and there is also a notification panel warning about storing unbucketable item within a bucket folder. I believe - that is an issue of person asking a question on StackOverflow (see image below). That new item has normal path as an immediate child of bucket folder (not date-specific as defaults for bucket items path) and looking into Item Buckets sections reveals that Bucketable checkbox is not set. To add this Article 6 item into bucket, one needs to check its Bucketable field and then perform Sync from the Ribbon above.


But why that behavior happens?


Solution: Well, this checkbox isn't set but should be on items creation. How do we get that behavior? Just checking that checkbox in corresponding template's Standard Values. Screenshot below shows Article template that is a data template for all Article items. Standard Values for template are always called as __Standard Values so fields set in that item (with static values or tokens) will be auto pre-set each time and item of that template is being created:



So, as soon we have updated Standard Values with Bucketable checked, we try to create another article (of the same template, for sure), we logically call it Article 7. Once created, Article 7 is already bucketable by its Standard Values and is immediately stored in the bucket. There's no need to perform Sync! It also preloads content area right hand side (or you may search for it from Search tab) and if you pay attention to an Item path field - it is being located exactly as specified in (default in our example) bucketing configuration:



Hope this post helps you to understand a concept that is hidden behind the buckets!

Mass update of field value for all existing items of certain template - two ways of achieving result

Given: I have multiple already existing items of a specific template across my content tree. Template has some field that I want to update with a new value for all existing items, within some node I can specify.

Use cases for that scenario are really universal - you may use that for various purposes. What comes into my head, at a first glance, is the situation when you would like to assign some template to a workflow but already have multiple existing items of that template (just to remind - setting a field value at Standard Values will apply for all new, but not existing items of that particular template). In that case you need assign a workflow to each existing item individually.

Another good example is when you have a folder with multiple items, growing in amount with time flow. Then you may decide to make a folder bucketable, but those existing items require to set a Bucketable checkbox for each existing item individually. I have described that case in one of my previous blog posts - "Understanding Buckets: adding new items to buckets correctly". So let's pick up second case and try to solve it.

Solution: So, what are possible ways of achieving that goal? Not so much of them, there are just two options.

1. Straightforward option - use C# code. With C# task may be achieved by a recursive method, that accepts an item, verifies if the one is of desired template and if yes - updates the field and does the same for all item's children if any. Here is an example of such method and example of call :

private void UpdateAllFieldsRecursively(Item parentItem, string templateName, string fieldName, string newValue)
{
    if (parentItem != null)
    {
        using (new SecurityDisabler())
        {
            foreach (Item childItem in parentItem.Children)
            {
                if (childItem.Fields[fieldName] != null && childItem.TemplateName == templateName)
                {
                    using (new EditContext(childItem))
                    {
                        childItem[fieldName] = newValue;
                    }
                }

                if (childItem.HasChildren)
                {
                    UpdateAllFieldsRecursively(childItem, templateName, fieldName, newValue);
                }
            }
        }
    }
}

// and below there is the call to recursive mehod
const string parentNode = "/sitecore/content";
var database = Sitecore.Context.Database;
var parentItem = database.GetItem(parentNode);

UpdateAllFieldsRecursively(parentItem, "Article", "Bucketable", "1");

The code above works out perfectly and does exactly what we want from it, however there are certain disadvantages: first of all you need to run the code in some context - call if from some existing class, for example. Second - as that is C# code - it must be re-compiled and re-deployed. And if you may need to amend small change into the code - will have to re-compile and re-deploy again. But, luckily, there is a much better and faster alternative:

2. PowerShell Module. That module integrates into the platform and offers unprecedentedly ultimate possibilities and power over Sitecore instance and databases. After installation there is PowerShell console and more advanced PowerShell ISE, where you may create and test scripts. They are executed immediately without any of prerequisites like rebuilt DLL with a code at your bin folder. So, here is a script that does exactly the same as previous C# code:

cd 'master:/sitecore/content'
Get-ChildItem -Recurse . | Where-Object { $_.TemplateName -match "Article" -and $_.Fields["Bucketable"] -ne $null } | ForEach-Object {
   
    $_.Editing.BeginEdit()
    $_.Fields["Bucketable"].Value = "1";
    $_.Editing.EndEdit()
    ""
}

PowerShell script above does exactly the same - iterates Sitecore tree for "Article" templates, starting recursively from /sitecore/content node and if anything found - updates the filed value.

Hope this code helps!