/// <summary> /// Gets the document. /// </summary> /// <param name="fetchXmlResult">The fetch XML result.</param> /// <returns></returns> /// <exception cref="System.InvalidOperationException"> /// </exception> public CrmEntityIndexDocument GetDocument(FetchXmlResult fetchXmlResult) { var entityMetadata = _dataContext.GetEntityMetadata(_fetchXml.LogicalName, _metadataCache); var attributes = entityMetadata.Attributes.ToDictionary(a => a.LogicalName, a => a); var document = new Document(); var primaryKey = Guid.Empty; var languageValueAdded = false; var lcid = 0; // Store the entity logical name and the logical name of the primary key attribute in the index document, for // easier later retrieval of the entity corresponding to this document. document.Add( new Field(_index.LogicalNameFieldName, entityMetadata.LogicalName, Field.Store.YES, Field.Index.NOT_ANALYZED)); document.Add( new Field( _index.PrimaryKeyLogicalNameFieldName, entityMetadata.PrimaryIdAttribute, Field.Store.YES, Field.Index.NOT_ANALYZED)); try { var content = new ContentFieldBuilder(); foreach (var fetchXmlField in fetchXmlResult) { // Treat the primary key field in a special way. if (fetchXmlField.Name == entityMetadata.PrimaryIdAttribute) { primaryKey = new Guid(fetchXmlField.Value); document.Add(new Field(_index.PrimaryKeyFieldName, primaryKey.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); document.Add(new Field(fetchXmlField.Name, primaryKey.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); // Adding webroles for the webpage to the index. if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)) { if (entityMetadata.LogicalName == "adx_webpage") { ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "CMS is enabled. Adding roles for adx_webpage index"); var ruleNames = CmsIndexHelper.GetWebPageWebRoles(this._contentMapProvider, primaryKey); this.AddWebRolesToDocument(document, ruleNames); } if (entityMetadata.LogicalName == "adx_ideaforum") { ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "CMS is enabled. Adding roles for adx_ideaforum index"); var ruleNames = CmsIndexHelper.GetIdeaForumWebRoles(this._contentMapProvider, primaryKey); this.AddWebRolesToDocument(document, ruleNames); } if (entityMetadata.LogicalName == "adx_communityforum") { ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "CMS is enabled. Adding roles for adx_communityforum index"); var ruleNames = CmsIndexHelper.GetForumsWebRoles(this._contentMapProvider, primaryKey); this.AddWebRolesToDocument(document, ruleNames); } } continue; } if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)) { if (fetchXmlField.Name == "adx_ideaforumid" && entityMetadata.LogicalName == "adx_idea") { ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "CMS is enabled. Adding roles for adx_idea index"); var ruleNames = CmsIndexHelper.GetIdeaForumWebRoles( this._contentMapProvider, new Guid(fetchXmlField.Value)); this.AddWebRolesToDocument(document, ruleNames); } // Based off the Parent Web Page get the webroles for each given entity if ((fetchXmlField.Name == "adx_parentpageid" && entityMetadata.LogicalName == "adx_blog") || (fetchXmlField.Name == "adx_blog_blogpost.adx_parentpageid" && entityMetadata.LogicalName == "adx_blogpost") || (fetchXmlField.Name == "adx_parentpageid" && entityMetadata.LogicalName == "adx_webfile")) { ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, string.Format("CMS is enabled. Adding roles for {0} index", fetchXmlField.Name)); var ruleNames = CmsIndexHelper.GetWebPageWebRoles(this._contentMapProvider, new Guid(fetchXmlField.Value)); this.AddWebRolesToDocument(document, ruleNames); } if ((fetchXmlField.Name == "adx_forumid" && entityMetadata.LogicalName == "adx_communityforumthread") || (fetchXmlField.Name == "adx_communityforumpost_communityforumthread.adx_forumid" && entityMetadata.LogicalName == "adx_communityforumpost")) { ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, string.Format("CMS is enabled. Adding roles for {0} index", fetchXmlField.Name)); var ruleNames = CmsIndexHelper.GetForumsWebRoles( this._contentMapProvider, new Guid(fetchXmlField.Value)); this.AddWebRolesToDocument(document, ruleNames); } if (entityMetadata.LogicalName == "annotation" && fetchXmlField.Name == "knowledgearticle.knowledgearticleid") { var id = new Guid(fetchXmlField.Value); document.Add(new Field("annotation_knowledgearticleid", id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); } } // Store the title of the result in a special field. if (fetchXmlField.Name == _titleAttributeLogicalName && entityMetadata.LogicalName != "annotation") { document.Add(new Field(_index.TitleFieldName, fetchXmlField.Value, Field.Store.YES, Field.Index.ANALYZED)); } // Store the language locale code in a separate field. if (_localeConfig.IsLanguageCodeLogicalName(fetchXmlField.Name)) { document.Add( new Field( _index.LanguageLocaleCodeFieldName, fetchXmlField.Value.ToLowerInvariant(), Field.Store.YES, Field.Index.NOT_ANALYZED)); languageValueAdded = true; } // Store the language locale LCID in a separate field. if (_localeConfig.IsLCIDLogicalName(fetchXmlField.Name) && int.TryParse(fetchXmlField.Value, out lcid)) { document.Add( new Field(_index.LanguageLocaleLCIDFieldName, fetchXmlField.Value, Field.Store.YES, Field.Index.NOT_ANALYZED)); } // Skip metadata parsing for language fields if (_localeConfig.CanSkipMetadata(fetchXmlField.Name)) { continue; } FetchXmlLinkAttribute link; if (_fetchXml.TryGetLinkAttribute(fetchXmlField, out link)) { var linkEntityMetadata = _dataContext.GetEntityMetadata(link.EntityLogicalName, _metadataCache); var linkAttributeMetadata = linkEntityMetadata.Attributes.FirstOrDefault(a => a.LogicalName == link.LogicalName); if (linkAttributeMetadata == null) { throw new InvalidOperationException("Unable to retrieve attribute metadata for FetchXML result field {0} for entity {1}.".FormatWith(link.LogicalName, linkEntityMetadata.LogicalName)); } var fieldName = fetchXmlResult.Any(f => f.Name == link.LogicalName) ? "{0}.{1}".FormatWith(linkEntityMetadata.LogicalName, linkAttributeMetadata.LogicalName) : link.LogicalName; //Renaming product identifier field to "associated.product" if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching) && (this._fetchXml.LogicalName == "knowledgearticle" && fieldName == "record2id" || this._fetchXml.LogicalName == "annotation" && fieldName == "productid")) { fieldName = FixedFacetsConfiguration.ProductFieldFacetName; } if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching) && (this._fetchXml.LogicalName == "knowledgearticle" && (fieldName == "notetext" || fieldName == "filename"))) { fieldName = "related_" + fieldName; } if (fieldName == "related_filename") { fetchXmlField.Value = Regex.Replace(fetchXmlField.Value, "[._,-]", " "); } if (fieldName == "related_notetext") { fetchXmlField.Value = fetchXmlField.Value.Substring(GetNotesFilterPrefix().Length); } AddDocumentFields(document, fieldName, fetchXmlField, linkAttributeMetadata, content); } else { AttributeMetadata attributeMetadata; if (!attributes.TryGetValue(fetchXmlField.Name, out attributeMetadata)) { throw new InvalidOperationException( ResourceManager.GetString("Attribute_Metadata_Fetchxml_Retrieve_Exception") .FormatWith(fetchXmlField.Name, entityMetadata.LogicalName)); } if (fetchXmlField.Name == "filename") { fetchXmlField.Value = Regex.Replace(fetchXmlField.Value, "[._,-]", " "); } if (fetchXmlField.Name == "notetext") { fetchXmlField.Value = fetchXmlField.Value.Substring(GetNotesFilterPrefix().Length); } AddDocumentFields(document, fetchXmlField.Name, fetchXmlField, attributeMetadata, content); } } if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)) { // Add the default value for entities that are not Knowledge articles for the Product filtering field. if (entityMetadata.LogicalName != "knowledgearticle") { document.Add( new Field( FixedFacetsConfiguration.ProductFieldFacetName, this._index.ProductAccessNonKnowledgeArticleDefaultValue, Field.Store.NO, Field.Index.NOT_ANALYZED)); document.Add( new Field(FixedFacetsConfiguration.ContentAccessLevel, "public", Field.Store.NO, Field.Index.NOT_ANALYZED)); } else { // If there aren't any products associated to the article add the default value so then at query time // based on the site setting it will add these to the result or not. var productsDocument = document.GetField(FixedFacetsConfiguration.ProductFieldFacetName); if (productsDocument == null) { document.Add( new Field( FixedFacetsConfiguration.ProductFieldFacetName, this._index.ProductAccessDefaultValue, Field.Store.NO, Field.Index.NOT_ANALYZED)); } } } if (!languageValueAdded) { document.Add(new Field(_index.LanguageLocaleCodeFieldName, _index.LanguageLocaleCodeDefaultValue, Field.Store.YES, Field.Index.NOT_ANALYZED)); } // Add the field for the main, analyzed, search content. document.Add(new Field(_index.ContentFieldName, content.ToString(), _index.StoreContentField ? Field.Store.YES : Field.Store.NO, Field.Index.ANALYZED)); if (_index.AddScopeField) { var scopeField = document.GetField(_index.ScopeValueSourceFieldName); var scopeValue = scopeField == null ? _index.ScopeDefaultValue : scopeField.StringValue; document.Add(new Field(_index.ScopeFieldName, scopeValue, Field.Store.NO, Field.Index.NOT_ANALYZED)); } if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)) { this.AddDefaultWebRoleToAllDocumentsNotUnderCMS(document, entityMetadata.LogicalName); this.AddUrlDefinedToDocument(document, entityMetadata.LogicalName, fetchXmlResult); } var documentAnalyzer = lcid > 0 ? _index.GetLanguageSpecificAnalyzer(lcid) : _index.Analyzer; return(new CrmEntityIndexDocument(document, documentAnalyzer, primaryKey)); } catch (Exception e) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Error: Exception when trying to create the index document. {0}", e)); } return(new CrmEntityIndexDocument(document, _index.Analyzer, primaryKey)); }