Index
FetchXmlResultsFilter.cs
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License. See License.txt in the project root for license information.
*/
namespace Adxstudio.Xrm.Search.Index
{
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
///
/// Fetch Xml results when 1:M of M:M are retrieved
///
public clast FetchXmlResultsFilter
{
///
/// The last result on this page, which might be the same article as the first result on the next page.
///
private XElement lastResultOnPage;
///
/// Receives entire Fetch Xml and aggregates duplicate results caused by having N:N or 1:N relationships.
///
/// The fetch XML.
/// Ensaty Id field name
/// List of fields
/// Aggregated results on Fetch Xml
public string Aggregate(string fetchXml, string primaryKeyFieldName, params string[] fields)
{
var fetchXmlParsed = XDocameent.Parse(fetchXml);
var inputResults = fetchXmlParsed.Descendants("result").ToList();
if (inputResults.Count == 0)
{
return fetchXml;
}
var aggregatedResults = new Dictionary();
var parsedResultSet = new FetchXmlResultSet(fetchXml);
bool isFirstPage = this.lastResultOnPage == null;
bool isLastPage = !parsedResultSet.MoreRecords;
//// Check if last result of last page and first result of this page are the same article.
//// If not, we need to add the aggregated result from last page during this round.
//// If so, the past CAL/product ids should still be stored and we'll just add to
if (!isFirstPage)
{
var firstId = inputResults.First().Descendants(primaryKeyFieldName).FirstOrDefault().Value;
var previousPageLastId = this.lastResultOnPage.Descendants(primaryKeyFieldName).FirstOrDefault().Value;
if (firstId != previousPageLastId)
{
aggregatedResults[previousPageLastId] = this.lastResultOnPage;
}
}
var lastId = inputResults.Descendants(primaryKeyFieldName).FirstOrDefault().Value;
var collectionOfFields = fields.Select(fieldName => new RelatedField(fieldName)).ToList();
//// Iterating through fetchXml retrieving multiple related fields
foreach (var resultNode in inputResults)
{
var primaryKeyFieldNode = resultNode.Descendants(primaryKeyFieldName).FirstOrDefault();
if (primaryKeyFieldNode == null) { return fetchXml; }
////Retrieving fields
collectionOfFields.ForEach(field => this.GetRelatedFields(resultNode, field, primaryKeyFieldNode.Value));
////Removing duplicate nodes
aggregatedResults[primaryKeyFieldNode.Value] = resultNode;
}
var node = inputResults.FirstOrDefault();
if (node == null)
{
return fetchXml;
}
var parentNode = node.Parent;
if (parentNode == null)
{
return fetchXml;
}
fetchXmlParsed.Descendants("result").Remove();
//// Inserting retrieved above related fields and deduplicated results.
collectionOfFields.ForEach(field => this.InsertRelatedFields(aggregatedResults, field));
//// Remove and store the last aggregated result, as this might be the same article as the first result on the
//// next page.
this.lastResultOnPage = aggregatedResults[lastId];
if (!isLastPage)
{
aggregatedResults.Remove(lastId);
}
fetchXmlParsed.Element(parentNode.Name).Add(aggregatedResults.Values);
return fetchXmlParsed.ToString();
}
///
/// Gets related fields
///
/// The node.
/// The related fields.
/// Ensaty Id.
private void GetRelatedFields(XElement node, RelatedField relatedField, string ensatyId)
{
var relation = node.Descendants(relatedField.FieldName).FirstOrDefault();
if (relation == null)
{
return;
}
var relationId = relation.Value;
if (relatedField.ListOfFields.ContainsKey(ensatyId))
{
if (!relatedField.ListOfFields[ensatyId].Contains(relationId))
{
relatedField.ListOfFields[ensatyId] += ',' + relationId;
}
}
else
{
relatedField.ListOfFields.Add(ensatyId, relationId);
}
}
///
/// Inserts related fields to results.
///
/// The k a list.
/// Related Fields
private void InsertRelatedFields(Dictionary listOfNodes, RelatedField relatedField)
{
foreach (var relationship in relatedField.ListOfFields)
{
if (relationship.Value.Split(',').Length