HomeDev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Extend ratings with composites

This topic describes how to associate additional information with a rating or the rating statistics to support the use cases of your application.

You may need to associate additional information with a rating or the rating statistics to support the use cases of your application. For example, a rating warrants a supporting explanation, so you want to store that text with the rating. Like other Optimizely Community API features, you can extend a rating with your design data by creating a Composite. See also Composites in Discover the platform.

Add a composite rating

To save a Composite Rating that you defined, use the Add<TExtension>(Rating,TExtension) method of the IRatingService. This method accepts an instance of the Rating class and an instance of TExtension. It returns an instance of Composite<Rating,TExtension>.

Consider the following class, which represents a sample of extension data:

public class MyRatingExtension {
  // ...
}

In the example below, a rating is composed with an instance of this extension class:

IRatingService ratingService;

// ...

var rater = Reference.Create("user://identifier/for/a/user");
var target = Reference.Create("resource://identifier/for/a/resource");
var value = new RatingValue(5);

var rating = new Rating(rater, target, value);

var extension = new MyRatingExtension {
  // ...
};

var compositeRating = ratingService.Add(rating, extension);

The above example invokes the request to add a rating synchronously. Below is an example of adding a rating asynchronously using the asynchronous overload with C#'s async and await keywords.

private async Task<Composite<Rating, MyRatingExtension>> AddRatingAsync(IRatingService ratingService) {
  DateTime dateOfPurchase;
  RatingId ratingOfQuality;

  // ...

  var rater = Reference.Create("user://identifier/for/a/user");
  var target = Reference.Create("resource://identifier/for/a/resource");
  var value = new RatingValue(5);

  var rating = new Rating(rater, target, value);

  var extension = new MyRatingExtension {
    // ...
  };

  var addRatingTask = ratingService.AddAsync(rating, extension);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var newRating = await addRatingTask;
  return newRating;
}

Update a composite rating

To update a specific instance of a Composite Rating, which was previously added through the platform, use the Update<TExtension>(RatingId, RatingValue, RatingValue, TExtension) method of the IRatingService. This method accepts the ID of the rating to be updated (RatingId), the current value of the rating (RatingValue), the new value of the rating to be set (RatingValue), and extension data related to rating.

📘

Note

This method accepts the current value of your Rating, in addition to the new value, to ensure consistency in the calculation of the statistical measures associated with that Rating.

Consider the following class, which represents a sample of extension data:

public class MyRatingExtension {
  // ...
}

In the example below, an existing rating is updated with an instance of this extension class:

IRatingService ratingService;
Rating originalRating;

// ...

var extension = new MyRatingExtension {
  // ...
};

ratingService.Update(originalRating.Id, originalRating.Value, new RatingValue(5), extension);

If the rating to be updated does not exist or the specified current value is no longer consistent with the stored representation of that rating, a RatingDoesNotExistException is thrown.

The above example invokes the request to update a rating synchronously. Below is an example of updating a rating asynchronously using the asynchronous overload with C#'s async and await keywords.

private async Task<Composite<Rating, MyRatingExtension>> UpdateRatingAsync(IRatingService ratingService) {
  // ...

  Rating originalRating;

  // ...

  var extension = new MyRatingExtension {
    // ...
  };

  var updateRatingTask = ratingService.UpdateAsync(originalRating.Id, originalRating.Value, new RatingValue(5), extension);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var updatedRating = await updateRatingTask;
  return updatedRating;
}

Retrieve a composite rating

To retrieve a specific instance of a Composite Rating, which was previously added through the platform, use the Get<TExtension>(RatingId) method. This method accepts an instance of the RatingId class, which identifies the particular rating to be retrieved. It returns the instance of the Composite<Rating,TExtension> class corresponding to that identifier.

IRatingService ratingService;

//...

// Construct a RatingId corresponding to the desired rating
var ratingId = RatingId.Create("...");
var compositeRating = ratingService.Get<MyRatingExtension>(ratingId);

If a Composite Rating with the specified ID and extension type cannot be found, a RatingDoesNotExistException is thrown.

The above example invokes the request to retrieve a rating synchronously. An example of retrieving a rating asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

private async Task<Composite<Rating, MyRatingExtension>> GetRatingAsync(IRatingService ratingService) {
  // ...

  // Construct a RatingId corresponding to the desired rating
  var ratingId = RatingId.Create("...");

  var getRatingTask = ratingService.GetAsync<MyRatingExtension>(ratingId);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var rating = await getRatingTask;
  return rating;
}

To retrieve a collection of Composite Ratings that were previously added through the platform, use the Get<TExtension>(CompositeCriteria<RatingFilter,TExtension>) method. This method accepts an instance of CompositeCriteria<RatingFilter,TExtension>, which contains specifications to retrieve the desired ratings.

The Filter property of the CompositeCriteria<RatingFilter,TExtension> class accepts an instance of the RatingFilter class. This class contains specifications for refining the result set of ratings you want to retrieve.

The ExtensionFilter property of the CompositeCriteria<RatingFilter,TExtension> class accepts a FilterExpression, which lets you specify a Boolean expression. Use the expression to refine the result set further by values in your extension data. For information on this type of filter, see Composite Criteria and Filter composites in Discover the platform.

Consider the following class, which represents a sample of extension data:

public class MyRatingExtension {
  public string Sentiment {
    get;
    set;
  }
}

In the example below, a page of ratings composed with MyRatingExtension is retrieved, where the Sentiment property of that extension data has a value of Happy:

IRatingService ratingService;

// ...

var criteria = new CompositeCriteria<RatingFilter,
  MyRatingExtension> {
    ExtensionFilter = FilterExpressionBuilder<MyRatingExtension> .Field(e => e.Sentiment).EqualTo("Happy")
  };

var resultPage = ratingService.Get(criteria);

In the above example, the request to retrieve ratings is invoked synchronously. An example of retrieving ratings asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

private async Task<ResultPage<Composite<Rating, MyRatingExtension>>> GetRatingsAsync(IRatingService ratingService) {
  // ...

  var criteria = new CompositeCriteria<RatingFilter,
    MyRatingExtension> {
      ExtensionFilter = FilterExpressionBuilder<MyRatingExtension> .Field(e => e.Sentiment).EqualTo("Happy")
    };

  var getRatingsTask = ratingService.GetAsync(criteria);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var pageOfRatings = await getRatingsTask;
  return pageOfRatings;
}

You can also apply the fields of your extension data to sort your result set. The example below demonstrates the use of an extension data field in defining a sorting rule.

var criteria = new CompositeCriteria<RatingFilter,
  MyRatingExtension> {
    // ...

    OrderBy = new List<SortInfo> {
      new SortInfo(new SortField(FilterExpressionBuilder<MyRatingExtension> .Field(t => t.Sentiment)), true),
      new SortInfo(RatingSortFields.Created, false),
    }
  };

Add composite rating statistics

Rating statistics are automatically generated by the platform when a rating for a referenced target is added. The platform does not automatically add composite data to the generated rating statistics. To add composite rating statistics, use the Update<TExtension>(Reference, TExtension) method of the IRatingStatisticsService. This method accepts a reference to the rated target and the extension data to be added to the rating statistics.

public class MyStatisticsExtension {
  // ... define whatever extension data is required ...
}
private RatingStatistics AddRatingStatistics(IRatingStatisticsService statisticsService) {
  var targetReference = Reference.Create("the-rated-target-reference");
  var extData = new MyStatisticsExtension {
    // ... fill extension data properties ...
  }

  return statisticsService.Update(targetReference, extData);
}

If the rating statistics cannot be found using the given target reference, a RatingStatisticsDoNotExistException is thrown.

In the above example, the request to add the extension data to the rating statistics is invoked synchronously. Below is an example of adding composite data to rating statistics asynchronously using the asynchronous overload with C#'s async and await keywords.

private async Task<RatingStatistics> AddRatingStatisticsAsync(IRatingStatisticsService statisticsService) {
  var targetReference = Reference.Create("the-rated-target-reference");
  var extData = new MyStatisticsExtension {
    // ... fill extension data properties ...
  }

  var updatedStatisticsTask = statisticsService.UpdateAsync(targetReference, extData);

  // ... do other application specific work in parallel while the task executes ...

  //Wait until the task runs to completion.
  var updatedRatingStatistics = await updatedStatisticsTask;
  return updatedRatingStatistics;
}

Update composite rating statistics

To update the extension data of composite rating statistics, use the Update<TExtension>(Reference, TExtension) method of the IRatingStatisticsService. This method accepts a reference to the rated target and the updated extension data.

public class MyStatisticsExtension {
  // ... define whatever extension data is required ...
}
private RatingStatistics UpdateRatingStatistics(IRatingStatisticsService statisticsService) {
  var targetReference = Reference.Create("the-rated-target-reference");
  var extData = new MyStatisticsExtension {
    // ... fill extension data properties ...
  }

  return statisticsService.Update(targetReference, extData);
}

If the rating statistics cannot be found using the given target reference, a RatingStatisticsDoNotExistException is thrown.

In the above example, the request to update the extension data of the rating statistics is invoked synchronously. Below is an example of updating the extension data of rating statistics asynchronously using the asynchronous overload with C#'s async and await keywords.

private async Task<RatingStatistics> UpdateRatingStatisticsAsync(IRatingStatisticsService statisticsService) {
  var targetReference = Reference.Create("the-rated-target-reference");
  var extData = new MyStatisticsExtension {
    // ... fill extension data properties ...
  }

  var updatedStatisticsTask = statisticsService.UpdateAsync(targetReference, extData);

  // ... do other application specific work in parallel while the task executes ...

  //Wait until the task runs to completion.
  var updatedRatingStatistics = await updatedStatisticsTask;
  return updatedRatingStatistics;
}

Retrieve composite rating statistics

To retrieve a collection of composite rating statistics, use the Get<TExtension>(CompositeCriteria<RatingStatisticsFilter,TExtension>) method. This method accepts an instance of CompositeCriteria<RatingStatisticsFilter,TExtension>, which contains specifications to retrieve the desired composite rating statistics.

The Filter property of the CompositeCriteria<RatingStatisticsFilter,TExtension> class accepts an instance of the RatingStatisticsFilter class. This class contains specifications for refining the result set of composite rating statistics you want to retrieve.

The ExtensionFilter property of the CompositeCriteria<RatingStatisticsFilter,TExtension> class accepts a FilterExpression, which lets you specify a Boolean expression. Use the expression to refine the result set further by values in your extension data. For information on this type of filter, see Composite Criteria and Filter composites in Discover the platform.

Consider the following class, which represents a sample of extension data:

public class MyRatingStatisticsExtension {
  public string WeightedAverage {
    get;
    set;
  }
}

In the example below, a page of rating statistics composed with MyRatingStatisticsExtension is retrieved, where the WeightedAverage property of that extension data has a value of 10:

IRatingStatisticsService statisticsService;

// ...

var criteria = new CompositeCriteria<RatingStatisticsFilter,
  MyRatingStatisticsExtension> {
    ExtensionFilter = FilterExpressionBuilder<MyRatingStatisticsExtension> .Field(e => e.WeightedAverage).EqualTo(10)
  };

var resultPage = statisticsService.Get(criteria);

The above example invokes the request to retrieve rating statistics synchronously. An example of retrieving rating statistics asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

private async Task<ResultPage<Composite<RatingStatistics, MyRatingStatisticsExtension>>> GetRatingsStatisticsAsync(IRatingStatisticsService statisticsService) {
  // ...

  var criteria = new CompositeCriteria<RatingStatisticsFilter,
    MyRatingStatisticsExtension> {
      ExtensionFilter = FilterExpressionBuilder<MyRatingStatisticsExtension> .Field(e => e.WeightedAverage).EqualTo(10)
    };

  var getRatingStatisticsTask = statisticsService.GetAsync(criteria);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var pageOfRatingStatistics = await getStatisticsTask;
  return pageOfRatingStatistics;
}

You can also apply the fields of your extension data to sort your result set. The example below demonstrates the use of an extension data field in defining a sorting rule.

var criteria = new CompositeCriteria<RatingStatisticsFilter,
  MyRatingStatisticsExtension> {
    // ...

    OrderBy = new List<SortInfo> {
      new SortInfo(new SortField(FilterExpressionBuilder<MyRatingStatisticsExtension> .Field(t => t.WeightedAverage)), true),
      new SortInfo(RatingSortFields.Created, false),
    }
  };

Next