I am using code from Shannons cg10 demo and implementing GatheringNodeData method. What I am trying to do is I have a product doc type, that has bunch of fields that are of type ultimate picker. The ultimate picker takes parent doc as source and lists child pages below it.
The data in the umbraco product document will store umbraco node ids. In the index i want to store a field value from the document selected by ultimate picker. My question is not all the fields on that product doc are of type ultimate picker so do i have to handle them seperately or will they get indexed as well? In my examine index config i am by default indexing all fields.
So code so far is something like:
if (e.IndexType == IndexTypes.Content)
{
if (e.Node.UmbNodeTypeAlias() == productAlias)
{
//if this is a 'product' page look at ultimate picker params
var node = new Node(e.NodeId);
// get all ultimate picker fields , get value then add to index acutal value
//put the combined comments into this blog post's index
e.Fields.Add("somefile", actualvalue);
}
}
In answer to my own question you do not need to handle the other fields separately, however you will get conflicts if you are adding fields so you need to ensure you give them another name, in my case i had field alias duration so i added it as __duration as it was already in as duration.
using System.Collections.Generic;
using umbraco.BusinessLogic;
using Examine;
using UmbracoExamine;
using umbraco.presentation.nodeFactory;
using System.Text;
using Umbraco_Site_Extensions.automation;
namespace Umbraco_Site_Extensions.examineExtensions
{
public class ExamineEvents:ApplicationBase
{
private const string WoiIndexer = "WOIIndexer";
private const string ProductAlias = "Product";
private readonly List<string> _ultimatePickerAliases = new List<string>{"theme","country","budgetFrom","budgetTo","participantFrom","participantTo","durationFrom","durationTo","periodFrom","periodTo"};
private const string NumericProperties =
"budgetFrom,budgetTo,participantFrom,participantTo,durationFrom,durationTo,periodFrom,periodTo";
/// <summary>
/// handles special cases for indexing of product properties
/// that are of type ultimate picker we want the actual value not node id in the index
/// </summary>
public ExamineEvents()
{
//Add event handler for 'GatheringNodeData' on our 'WOI'
ExamineManager.Instance.IndexProviderCollection[WoiIndexer].GatheringNodeData
+= ExamineEvents_GatheringNodeData;
}
/// <summary>
/// Event handler for GatheringNodeIndex.
/// This will fire everytime Examine is creating/updating an index for an item
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ExamineEvents_GatheringNodeData(object sender, IndexingNodeDataEventArgs e)
{
//check if this is 'Content' (as opposed to media, etc...)
if (e.IndexType == IndexTypes.Content)
{
if (e.Node.UmbNodeTypeAlias() == ProductAlias)
{
//if this is a 'product' page look at ultimate picker params
var node = new Node(e.NodeId);
foreach (var ultimateAlias in _ultimatePickerAliases) {
var propertyValue = node.GetPropertyValue(ultimateAlias);
if(propertyValue!=string.Empty)
{
if(propertyValue.Contains(","))
{
string[] propValues = propertyValue.Split(new[] {','});
var sbConcatValue=new StringBuilder();
foreach (var propValue in propValues)
{
sbConcatValue.Append(GetFieldValue(e, propValue, ultimateAlias));
sbConcatValue.Append(",");
}
e.Fields.Add("__" + ultimateAlias, sbConcatValue.ToString().TrimEnd(','));
}
else
{
e.Fields.Add("__" + ultimateAlias,GetFieldValue(e, propertyValue, ultimateAlias));
}
}
}
}
AddToContentsField(e);
}
}
private void AddToContentsField(IndexingNodeDataEventArgs e)
{
Dictionary<string, string> fields = e.Fields;
var combinedFields = new StringBuilder();
foreach (KeyValuePair<string, string> keyValuePair in fields)
{
combinedFields.AppendLine(keyValuePair.Value);
}
e.Fields.Add("contents",combinedFields.ToString());
}
/// <summary>
/// get ultimate picker field acutal value not the id of target
/// </summary>
/// <param name="e"></param>
/// <param name="propertyValue"></param>
/// <param name="luceneFieldAlias"></param>
/// <returns></returns>
private string GetFieldValue(IndexingNodeDataEventArgs e, string propertyValue,string luceneFieldAlias)
{
int nodeId = 0;
int.TryParse(propertyValue, out nodeId);
var n= new Node(nodeId);
//node does not exist but we have numeric value
if(n.Id!=0){
if (NumericProperties.Contains(luceneFieldAlias))
{
//have to pad out to get lucene range queries to work
int i = 0;
int.TryParse(n.Name, out i);
return i.ToString("D6");
}
else{
return n.Name;
}
}
return nodeId.ToString("D6");
}
}
}
Just a quick question about the ExamineEvents class (posted above)... After you add it to your project (UmbracoExtensions in my case) do you need to do any change to the ExamineSettings.config or to the ExamineIndex.config? I am using this class to solve a very similar issue (just like the original post), although, after all the changes to the (my) DocumentAlias, properties, etc... it didn't work out for me. And I can't seem debug it as well...
Everything compiles great, although, when I check the Index (using Luke) I don't see the __LeftBlocks, etc (...) fields. I would expect them to be generated as well. Like I told before, I can't debug the class also. Therefore, I am not really sure if this custom UmbracoExamie event handler is being fired up.
Hey - following worked for me, had a problem as we needed to query the ParentID on Media objects. ParentID does not appear to be an attribute of the actual media item, so simple adding this to the ExamineIndex.config did not work. Seems you have to get the containing (I guess is the right word?) node for the Media item, and then stuff that into your index as a new fields:
I know its been a while since this original post but I am now do something similar to this where I can access properties of a node on the GatheringNodeData event but rather than using the umbraco.presentation.nodeFactory, I am now using the umbraco.NodeFactory ....
if (!string.IsNullOrEmpty(origNodeID)) { Node origNode = new Node(int.Parse(origNodeID)); e.Fields["bodyText"] = origNode.GetProperty("bodyText").Value; }
}
However, I can get a handle on the property but the Value is throwing an exception:
'((new System.Collections.Generic.Mscorlib_CollectionDebugView(origNode.PropertiesAsList)).Items[0]).Value' threw an exception of type 'System.NullReferenceException'
For the hell of me I couldn’t get this to work. I could see the index happening and the fields getting loaded with the “__”. But could not retrieve the information with a search.
Then I went and removed the fields instead of adding a new “__” and replaced the values with the retrieved value. Then it worked. What was I missing here. Have a look at the data below and look at the country field If I searched for 1161 I got information back from examine if I searh for "South Africa" I there were no returns.
Why couldnt I retrive any info with the pre-value with a double underscore
GatheringNodeData examine event
Guys,
I am using code from Shannons cg10 demo and implementing GatheringNodeData method. What I am trying to do is I have a product doc type, that has bunch of fields that are of type ultimate picker. The ultimate picker takes parent doc as source and lists child pages below it.
The data in the umbraco product document will store umbraco node ids. In the index i want to store a field value from the document selected by ultimate picker. My question is not all the fields on that product doc are of type ultimate picker so do i have to handle them seperately or will they get indexed as well? In my examine index config i am by default indexing all fields.
So code so far is something like:
Regards
Ismail
In answer to my own question you do not need to handle the other fields separately, however you will get conflicts if you are adding fields so you need to ensure you give them another name, in my case i had field alias duration so i added it as __duration as it was already in as duration.
Regards
Ismail
Hi Ismail,
This is exactly what I need to do too.
How did you get on, do you possibly have any code you could share?
Many thanks
Rich
Rich,
my examine gathering node class looks like this
Regards
Ismail
Hi Ismail,
Thanks alot, I'll let you know how I get on.
Cheers
Rich
I've got the Indexer event wired in, many thanks Ismail/Aaron/Shannon.
Ismail, I think what you're doing is more complex than my issue as you have mulitiple pickers on the same doc type.
I only have one so in theory I assume I need to split each csv into it's own index.
And then I'll be able to use some type of "and" criteria to work out id this the search for 1057 and 1060 matches?
Would be good if I can confirm I'm going down the correct path...
Cheers
Rich
Gents,
Just a quick question about the ExamineEvents class (posted above)... After you add it to your project (UmbracoExtensions in my case) do you need to do any change to the ExamineSettings.config or to the ExamineIndex.config? I am using this class to solve a very similar issue (just like the original post), although, after all the changes to the (my) DocumentAlias, properties, etc... it didn't work out for me. And I can't seem debug it as well...
private const string WoiIndexer = "TheIndex";
private readonly List<string> DocumentTypeAlias = new List<string> { "ProjectOverview", "ProjectPage" };
private readonly List<string> _ultimatePickerAliases = new List<string> { "LeftBlocks", "MiddleBlocks", "RightBlocks" };
private const string NumericProperties = "LeftBlocks,MiddleBlocks,RightBlocks";
Hope to hear back from you soon.
Cheers,
Carlos
Hi Carlos,
Which version of Examine are you running?
Rich
Lucene.net.dll > File version: 2.9.2.1
UmbracoExamine.dll > File version: 0.9.2.0
Hi,
I have the code above working with (shipped with Umbraco 4.5.2)
Lucene.net.dll > File version: 2.9.2.2
UmbracoExamine.dll > File version: 0.9.2.2
Not sure if this makes a difference.
What is your exact problem, does the project not compile or are the indexes not being added?
Rich
Hi Rich,
Everything compiles great, although, when I check the Index (using Luke) I don't see the __LeftBlocks, etc (...) fields. I would expect them to be generated as well. Like I told before, I can't debug the class also. Therefore, I am not really sure if this custom UmbracoExamie event handler is being fired up.
Cheers,
Carlos
Hi Carlos,
Two things I can suggest.
One is to make sure you are referencing the correct indexer from the ExamineSettings.Config file (I made this mistake)
Second, add a debug to the log to see if the event is getting fired (you'll need to reference using umbraco.BusinessLogic;)
I couldn't get debugging to work either (I didn't try too hard), so I just used the log to debug as above.
Best of luck
Rich
Hi Rich,
That was it... I was referencing my IndexSet not the Indexer. It works now!
Thank you for your quick help!
Cheers,
Carlos
Ismail,
After you've added the special indexes for MNTP in the GatheringNodeData event, how & when do you remove them?
Say if I deselect a value from a MNTP field surely I have to remove the index?
Rich
Yeah it'll be updated. It runs off the Umbraco XML so if that changes then the index should change.
Hey - following worked for me, had a problem as we needed to query the ParentID on Media objects.
ParentID does not appear to be an attribute of the actual media item, so simple adding this to the ExamineIndex.config did not work.
Seems you have to get the containing (I guess is the right word?) node for the Media item, and then stuff that into your index as a new fields:
Hi
I know its been a while since this original post but I am now do something similar to this where I can access properties of a node on the GatheringNodeData event but rather than using the umbraco.presentation.nodeFactory, I am now using the umbraco.NodeFactory ....
private void IndexShadowProduct(IndexingNodeDataEventArgs e, Node node)
{
string origNodeID = e.Fields["umbracoInternalRedirectId"].ToString();
if (!string.IsNullOrEmpty(origNodeID))
{
Node origNode = new Node(int.Parse(origNodeID));
e.Fields["bodyText"] = origNode.GetProperty("bodyText").Value;
}
}
However, I can get a handle on the property but the Value is throwing an exception:
'((new System.Collections.Generic.Mscorlib_CollectionDebugView(origNode.PropertiesAsList)).Items[0]).Value' threw an exception of type 'System.NullReferenceException'
Any ideas? Thanks in advance
Marie
For the hell of me I couldn’t get this to work. I could see the index happening and the fields getting loaded with the “__”. But could not retrieve the information with a search.
Then I went and removed the fields instead of adding a new “__” and replaced the values with the retrieved value. Then it worked. What was I missing here. Have a look at the data below and look at the country field If I searched for 1161 I got information back from examine if I searh for "South Africa" I there were no returns.
Why couldnt I retrive any info with the pre-value with a double underscore
if (propertyValue != string.Empty)
{
if (propertyValue.Contains(","))
{
string[] propValues = propertyValue.Split(new[] { ',' });
var sbConcatValue = new StringBuilder();
foreach (var propValue in propValues)
{
sbConcatValue.Append(GetFieldValue(e, propValue, ultimateAlias));
sbConcatValue.Append(",");
}
e.Fields.Remove(ultimateAlias);
e.Fields.Add(ultimateAlias, sbConcatValue.ToString().TrimEnd(','));
}
else
{
e.Fields.Remove(ultimateAlias);
e.Fields.Add(ultimateAlias, GetFieldValue(e, propertyValue, ultimateAlias));
}
}
+[0]{[businessName, Full Throttle]}System.Collections.Generic.KeyValuePair<string,string>
+[1]{[businessDescription, Aliquam sit amet sapien mauris! }System.Collections.Generic.KeyValuePair<string,string>
+[2]{[country, 1161]}System.Collections.Generic.KeyValuePair<string,string>
+[3]{[region, 1164,1165]}System.Collections.Generic.KeyValuePair<string,string>
+[4]{[province, 1162]}System.Collections.Generic.KeyValuePair<string,string>
+[5]{[cities, 1167]}System.Collections.Generic.KeyValuePair<string,string>
+[6]{[id, 1219]}System.Collections.Generic.KeyValuePair<string,string>
+[7]{[nodeName, Full Throttle]}System.Collections.Generic.KeyValuePair<string,string>
+[8]{[updateDate, 2013-03-01T13:51:44]}System.Collections.Generic.KeyValuePair<string,string>
+[9]{[writerName, admin]}System.Collections.Generic.KeyValuePair<string,string>
+[10]{[loginName, fullthrottle]}System.Collections.Generic.KeyValuePair<string,string>
+[11]{[email, [email protected]]}System.Collections.Generic.KeyValuePair<string,string>
+[12]{[nodeTypeAlias, Client]}System.Collections.Generic.KeyValuePair<string,string>
+[13]{[__country, South Africa]}System.Collections.Generic.KeyValuePair<string,string>
+[14]{[__province, Gauteng]}System.Collections.Generic.KeyValuePair<string,string>
+[15]{[__region, West Rand,East Rand]}System.Collections.Generic.KeyValuePair<string,string>
+[16]{[__cities, Boksburg]}System.Collections.Generic.KeyValuePair<string,string>
<ExamineLuceneIndexSets>
<!-- The internal index set used by Umbraco back-office - DO NOT REMOVE -->
<IndexSet SetName="InternalIndexSet" IndexPath="~/App_Data/TEMP/ExamineIndexes/Internal/"/>
<!-- The internal index set used by Umbraco back-office for indexing members - DO NOT REMOVE -->
<IndexSet SetName="InternalMemberIndexSet" IndexPath="~/App_Data/TEMP/ExamineIndexes/InternalMember/">
<IndexAttributeFields>
<add Name="id" />
<add Name="nodeName"/>
<add Name="updateDate" />
<add Name="writerName" />
<add Name="loginName" />
<add Name="email" />
<add Name="nodeTypeAlias" />
</IndexAttributeFields>
<IndexUserFields>
<add Name="businessName" />
<add Name="businessDescription" />
<add Name="country" />
<add Name="region" />
<add Name="province" />
<add Name="cities" />
<add Name="__country" />
<add Name="__region" />
<add Name="__province" />
<add Name="__cities" />
<add Name="contents" />
</IndexUserFields>
</IndexSet>
<!-- Default Indexset for external searches, this indexes all fields on all types of nodes-->
<IndexSet SetName="ExternalIndexSet" IndexPath="~/App_Data/TEMP/ExamineIndexes/External/" />
</ExamineLuceneIndexSe
is working on a reply...