Bulk content load and Page Creation in Sitecore - sitecore

I have a process where i am getting xml resultset , from which i can process the data and programmatically create pages in Sitecore. This is simple if we have to few pages that even once .
Now my problem is that i have to create minimum 50k pages in Sitecore twice a day from xml.So to load that much data in sitecore once is really slow process.
Is there is a optimum way to create these pages in Sitecore .
I am using Sitecore 7.
process for page creation
using (new Sitecore.SecurityModel.SecurityDisabler())
{
for (int i = 0; i < item.count; i++)
{
Item newCityItem = parentCityItem.Add("Page_" + i, template1);
newCityItem.Editing.BeginEdit();
try
{
newCityItem.Fields["html"].Value = mPages[i].ToString();
newCityItem.Editing.EndEdit();
}
catch (System.Exception ex)
{
// The update failed, write a message to the log
Sitecore.Diagnostics.Log.Error("Could not update item " + newCityItem.Paths.FullPath + ": " + ex.Message, this);
// Cancel the edit (not really needed, as Sitecore automatically aborts // the transaction on exceptions, but it wont hurt your code)
newCityItem.Editing.CancelEdit();
}
}
}
Any help ...

Wrap your loop in a BulkUpdateContext which disables events, indexes, etc
using(new BulkUpdateContext())
{
// code here
}

I don't think it's another way to create Sitecore Items.
What I suggest you, to disable indexing on master database, because it will slow a little bit when new items are created. If you need to index after creating your items you can enable again the indexes and start reindexing.

If these items are being replaced twice a day in Sitecore, I assume that they're not being edited and you're using Sitecore for the presentation layer.
If so, you could map your xml as a Sitecore DataProvider. This way, the xml is used as the source of the items - although they can still be read in Sitecore, and the Sitecore presentation layer sees them as regular sitecore items.
There's a blog post explaining it at http://blog.horizontalintegration.com/2013/03/17/an-introduction-to-sitecore-data-providers/, as well as some documentation in the SDN.
Edit (thanks to jammykam)
I wouldn't map direct to an xml file - maybe put that into a db and then map that into sitecore.

Everytime when you save an item, the statistics were updated (like modified user, modified date etc.) and all the events were fired (item saved, index building, etc). You can disable both of these:
item.Editing.BeginEdit();
item["Title"] = "My new title";
item.Editing.EndEdit(false, true);
Depending on your requirements you may need to rebuild the index at the end of your import.

Related

How to get all goals triggered during Sitecore session in commitDataSet Analytics pipeline?

I have an Analytics pipeline added just before the standard one in section to delete duplicate triggered pageevents before submitting all to database so I can have unique triggered events as there seems to be a bug on android/ios devices that triggers several events within few seconds interval.
In this custom pipeline I need to get the list of all goals/events the current user triggered in his session so I can compare with the values in dataset obtained from args parameter and delete the ones already triggered.
The args.DataSet.Tables["PageEvents"] only returns the set to be submitted to database and that doesn't help since it is changing each time this pipeline runs. I also tried Sitecore.Analytics.Tracker.Visitor.DataSet but I get a null value for these properties.
Does anyone knows a way how to get a list with all goals the user triggered so far in his session without requesting it directly to the database ?
Some code:
public class CommitUniqueAnalytics : CommitDataSetProcessor
{
public override void Process(CommitDataSetArgs args)
{
Assert.ArgumentNotNull(args, "args");
var table = args.DataSet.Tables["PageEvents"];
if (table != null)
{
//Sitecore.Analytics.Tracker.Visitor.DataSet.PageEvents - this list always empty
...........
}
}
}
I had a similar question.
In Sitecore 7.5 I found that this worked:
Tracker.Current.Session.Interaction.Pages.SelectMany(x=>x.PageEvents)
However I'm a little worried that this will be inefficient if the Pages collection is very large.

EmberJS client side record management (ember-data)

I have just started trying to use ember-data. I have an ember app for which I need to produce all the data on the client side and then save it all at once. So my object graph has a "Project" as the root object, then a project can have many "Sections" and then each section can have many "Items".
I am up to the stage where I am trying to create Item records on the client side and add them to the correct Section. When I am ready to save the data I just want to use project.save() and have it go and save the object graph instead of saving every time the model changes.
I am trying to look up the section to place the items in by name using store.filter({name:"section1"}) but ember keeps trying to go to the server to look them up. I see this in the console: GET http://localhost:4200/sections?name=Section1 404 (Not Found).
This is what I am trying to do:
store.filter('section', {name:'Section1'}, function(section) {
return section;
}).then(function(section)
{
var record;
//create a record
section.pushObject(record);
});
You are doing server side filtering and you want client side filtering.
Please read this article carefully.
In short, you should do
store.filter('section', function(section) {
return section.get('name') == 'Section1';
});

Sitecore 7 Analytics increase engagement value programatically

I am working on implementing sitecore DMS in 7.2 and I'm having one main issue for which I seem to be having a hard time finding an answer. I have some goals and events set up and I am attempting to set one off through the Analytics API. The event is being logged as being set off in the PageEventId database, but what I am trying to do is add Engagement Value to the current visit/visitor.
I'm looking to update the Value field in the Visits database for the current visit. Here is what I am currently using:
public static void triggerGoal(ID goal)
{
if (Tracker.IsActive && Tracker.CurrentPage != null)
{
Sitecore.Data.Items.Item goalToTrigger = Sitecore.Context.Database.GetItem(goal);
if (goalToTrigger != null)
{
Sitecore.Analytics.Data.Items.PageEventItem reg = new Sitecore.Analytics.Data.Items.PageEventItem(goalToTrigger);
Sitecore.Analytics.Data.DataAccess.DataSets.VisitorDataSet.PageEventsRow eventData =
Tracker.CurrentPage.Register(reg);
eventData.Data = goalToTrigger["Description"];
Tracker.Submit();
}
}
}
This updates the PageEventId database properly, noting that the event has been triggered, but this adds no Engagement Value to the Visits database, regardless of how many engagement points are assigned to the Goad that is being triggered.
I've tried various ways of getting the API to update this field, but nothing has worked for me so far. Here are a bunch of the different things I've tried:
Tracker.CurrentVisit.BeginEdit();
Tracker.CurrentVisit.Value += 3; //look up value here instead of hardcoding. Create new PageEventItem class to get field ID.
Tracker.CurrentVisit.AcceptChanges();
Tracker.CurrentVisit.EndEdit();
Tracker.CurrentVisit.Load();
Tracker.CurrentPage.BeginEdit();
Tracker.CurrentPage.Visit.Value += 3;
Tracker.CurrentPage.AcceptChanges();
Tracker.CurrentPage.EndEdit();
Tracker.Visitor.CurrentVisit.BeginEdit();
Tracker.Visitor.CurrentVisit.Value += 3;
Tracker.Visitor.CurrentVisit.AcceptChanges();
Tracker.Visitor.CurrentVisit.EndEdit();
Tracker.Visitor.CurrentVisit.Load();
Tracker.CurrentVisit.CurrentPage.Visit.BeginEdit();
Tracker.CurrentVisit.CurrentPage.Visit.Value += 3;
Tracker.CurrentVisit.CurrentPage.Visit.AcceptChanges();
Tracker.CurrentVisit.CurrentPage.Visit.EndEdit();
Tracker.CurrentVisit.CurrentPage.Visit.Load();
Tracker.CurrentVisit.CurrentPage.VisitorsRow.BeginEdit();
Tracker.CurrentVisit.CurrentPage.VisitorsRow.Value += 3;
Tracker.CurrentVisit.CurrentPage.VisitorsRow.AcceptChanges();
Tracker.CurrentVisit.CurrentPage.VisitorsRow.EndEdit();
I've used different combinations of using the AcceptChanges() and BeginEdit() EndEdit() and Load() functions, as I'm not completely sure what they each do, but either way, none of them update the Value field.
I am trying to avoid doing a custom SQL query to update this field, I'm trying to figure out how to do it through the built-in Sitecore Analytics API. Can anyone help me figure out how to update this field?
The following works fine for me, are you waiting long enough to see the value written for the visit?
if (Tracker.IsActive)
{
Tracker.CurrentVisit.Value += 3;
}
No need to BeginEdit, AcceptChanges, EndEdit, etc.
What you've done should work so long as you have set up your goal correctly in Sitecore. I like to mirror sitecore's default goals, and create goals of the "Page Event" template. Make sure that you've assigned the goal to your content item Analyze Tab -> Goals -> [select your goal from checkbox list]. If you're going to set the CurrentVisit value, I suggest using the line below to prevent hardcoding the engagement point values.
//This line will add points specified in Content Editor
Tracker.CurrentVisit.Value += int.Parse(reg.Points);
This document explains how to set up your goals the correct way. And if you follow it, your code will work the way you have it, reporting the value specified in the Content Editor without setting CurrentVisit.Value.
Sitecore SDN - Marketing Operations Cookbook

Can I guarantee publishing of an item I've just created?

I've got a situation where I want end-users to be able to create new Sitecore items... and then immediately be able to navigate to the Item's URL. Obviously the item will have to be published... but this happens in something of a black box. Is there a way to guarantee an item has been published from Master to Web?
Alternately, I could create the Item in the Web DB... then re-create/copy a Master version at some point. But this strategy seems fraught with peril. And maybe just a bad idea in general.
Suggestions? Am I being needlessly paranoid about creating items directly in Web?
I'll start by saying my answer is not necessarily advisable. However, depending on your situation it should work.
If the items that users are creating always have the same template you could try creating a custom item resolver that falls back to using the Master database.
Allow Sitecore to attempt to resolve the item normally.
When it fails, look in the Master database.
If the item is in there, make sure it has the correct template
Set the found item as the context item.
Using this method, you can publish the items from Master->Web s normal, but you don't have to wait until publishing is completed to see it.
Once again, this should solve the problem, but it's up to you to weigh the risks of serving up Master DB content.
You can't "guarantee" because publishing may be queued and won't go live instantly. Instead if you need instant access, I recommend a preview site that points to the master database:
How to Setup a Sitecore Preview Site to Review Content Before Publishing
You could create a event mapping to a class with the code to publish the item. In the code you can define any rule you want regarnding whether to publish or not.
<event name="item:saved">
<handler type="YourType.ItemEventHandler, YourType" method="OnItemSaved" />
</event>
And the OnItemSaved would look like this: (not tested)
protected void OnItemSaved(object sender, EventArgs args)
{
if (args == null)
{
return;
}
Item item = Event.ExtractParameter(args, 0) as Item;
var webDb = Sitecore.Configuration.Factory.GetDatabase("web");
var masterDb = Sitecore.Configuration.Factory.GetDatabase("master");
foreach (Language language in masterDb.Languages)
{
var options = new PublishOptions(masterDb, webDb, PublishMode.SingleItem, language, DateTime.Now)
{ RootItem = item, Deep = true };
var myPublisher = new Publisher(options);
myPublisher.Publish();
}
}
And about creating the item in the web db, I also wouldn`t go that way. It would be replaced by the default publishing process unexpectedly.
Personally i don't like front-end user creating items in master database, i feel only content authors/editors should be the ones who create items from either content editor or page editor.
There is no guarantee the item gets published instantly, I would recommend you to store any user-created data in a separate database and on the redirect URL just read the data from this database.

SharePoint List item BRIEFLY appears as edited by 'System Account' after item.update

I have a shopping cart like application running on SharePoint 2007.
I'm running a very standard update procedure on a list item:
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList list = web.Lists["Quotes"];
SPListItem item = list.GetItemById(_id);
item["Title"] = _quotename;
item["RecipientName"] = _quotename;
item["RecipientEmail"] = recipientemail;
item["IsActive"] = true;
item.Update();
site.Dispose();
}
This item updates properly, however it briefly appears as modified by System Account. If I wait a second and refresh the page, it shows up again as modified by CurrentUser.
This is an issue because on Page_Load I am retrieving the item that is marked as Active AND is listed as Modified By the CurrentUser. This means as a user updates his list, when the PostBack finishes, it shows he has no active items.
Is it the web.AllowUnsafeUpdates? This is necessary because I was getting a security error before.
What am I missing?
First off, it's not AllowUnsafeUpdates. This simply allows modifying of items from your code.
It's a bit hard to tell what's going on without understanding more of the flow of your application. I would suggest though that using Modified By to associate an item to a user may not be a great idea. This means, as you have discovered, that any modification by the system or even potentially an administrator will break that link.
I would store the current user in a custom field. That should solve your problem and would be a safer design choice.
There could be some other code running in Event Receivers and updating the item. Because event recievers runs in context of system user account, and if you update item from event reciever, the modified field will show just that: the system account has modified the item.