---
title: Search for orders using abstractions
slug: commerce-connect-15/docs/search-for-orders-using-abstractions
docTags: 
createdAt: 2026-07-30T20:34:41.000Z
---

```csharp
/// <summary>
/// Finds orders with a specific <see cref="OrderSearchFilter"/> for a specific <typeparamref name="TOrderGroup"/>.
/// </summary>
/// <typeparam name="TOrderGroup">The given order type for filter.</typeparam>
/// <param name="filter">The search filter.</param>
/// <returns>The order search results.</returns>
OrderSearchResults Find(OrderSearchFilter filter) where TOrderGroup : class, IOrderGroup;
```

The `Find` method returns `OrderSearchResults` for the orders matching the supplied `OrderSearchFilter` and `TOrderGroup` type parameter.

## Filter orders in search

`OrderSearchFilter` defines criteria for filtering orders in the search results:

- `CreatedFrom` – The earliest creation time for returned orders (inclusive).
- `CreatedTo` – The latest creation time for returned orders (inclusive).
- `MarketId` – Restricts results to orders created in the specified markets.
- `ModifiedFrom` – The earliest modification time for returned orders (inclusive).
- `ModifiedTo` – The latest modification time for returned orders (inclusive).
- `StartingIndex` – The starting index for paging through results.
- `RecordsToRetrieve` – The number of records to retrieve per page.

:::hint{type="info"}
**Note**
The search is inclusive; begin and end values are included for datetime filters (`CreatedFrom`, `CreatedTo`, `ModifiedFrom`, `ModifiedTo`).
:::

## Search results for orders

`OrderSearchResults` contains the matching orders in `Orders` (an `IEnumerable<T>`) and the total match count in `TotalRecords`.

As with other abstraction APIs, you can replace the default implementation with a custom one.

```csharp
using EPiServer.Framework;
using EPiServer.ServiceLocation;
using Mediachase.Commerce.Orders;
using Mediachase.Commerce.Orders.Search;
using Mediachase.MetaDataPlus.Extensions;
using System;
using System.Linq;

namespace EPiServer.Commerce.Order.Internal {
  /// <summary>
  /// This class is intended to be used internally by EPiServer.
  /// We do not support any backward compatibility on this.
  /// 
  /// Default implementation of .
  /// </summary>
  [ServiceConfiguration(ServiceType = typeof (IOrderSearchService), Lifecycle = ServiceInstanceScope.Singleton)]
  public class DefaultOrderSearchService: IOrderSearchService {
    private readonly ICartSearchService _cartSearch;

    public DefaultOrderSearchService(ICartSearchService cartSearch) {
      Validator.ThrowIfNull(nameof(cartSearch), cartSearch);
      _cartSearch = cartSearch;
    }

    public virtual OrderSearchResults Find(OrderSearchFilter filter) where TOrderGroup: class, IOrderGroup {
      Validator.ThrowIfNull(nameof(filter), filter);
      var type = typeof (TOrderGroup);
      if (IsCart(type)) {
        var carts = _cartSearch.FindCarts(filter.CreatedFrom, filter.CreatedTo,
          filter.MarketId, filter.StartingIndex ?? 0,
          filter.RecordsToRetrieve ?? int.MaxValue,
          out int totalRecords).OfType();
        return new OrderSearchResults(carts, totalRecords);
      }

      string sqlMetaWhereClause = $ @ "(META.Created BETWEEN '{(filter.CreatedFrom ?? DateTime.MinValue.TruncateToSqlDateTimeRange()).ToString("
      s ")}' 
      AND '{(filter.CreatedTo ?? DateTime.MaxValue.TruncateToSqlDateTimeRange()).ToString("s")}')
    ";

    sqlMetaWhereClause += $ @ " AND (META.Modified BETWEEN '{(filter.ModifiedFrom ?? DateTime.MinValue.TruncateToSqlDateTimeRange()).ToString("
    s ")}' 
    AND '{(filter.ModifiedTo ?? DateTime.MaxValue.TruncateToSqlDateTimeRange()).ToString("s")}')
  ";

  var parameters = new OrderSearchParameters() {
    SqlMetaWhereClause = sqlMetaWhereClause
  };

  if (!string.IsNullOrEmpty(filter.MarketId)) {
    parameters.SqlWhereClause = $ "MarketId = '{filter.MarketId}'";
  }

  var options = new OrderSearchOptions {
    StartingRecord = filter.StartingIndex ?? 0,
      RecordsToRetrieve = filter.RecordsToRetrieve ?? int.MaxValue
  };

  if (IsPurchaseOrder(type)) {
    options.Classes.Add(OrderContext.Current.PurchaseOrderMetaClass.Name);
    var orders = OrderContext.Current.FindPurchaseOrders(parameters, options, out int totalRecords).OfType();
    return new OrderSearchResults(orders, totalRecords);
  }

  if (IsPaymentPlan(type)) {
    options.Classes.Add(OrderContext.Current.PaymentPlanMetaClass.Name);
    var paymentplans = OrderContext.Current.FindPaymentPlans(parameters, options, out int totalRecords).OfType();
    return new OrderSearchResults(paymentplans, totalRecords);
  }

  throw new InvalidOperationException($"The type {typeof(TOrderGroup)} is not supported.");
}

private static bool IsCart(Type type) {
  return typeof (ICart).IsAssignableFrom(type);
}

private static bool IsPurchaseOrder(Type type) {
  return typeof (IPurchaseOrder).IsAssignableFrom(type);
}

private static bool IsPaymentPlan(Type type) {
  return typeof (IPaymentPlan).IsAssignableFrom(type);
}
}
}
```

## Extension methods

`IOrderSearchServiceExtensions` provides convenient extension methods for `IOrderSearchService`:

- `FindCarts`
- `FindPurchaseOrders`
- `FindPaymentPlans`

```csharp
var orderFilter = new OrderSearchFilter {
  CreatedFrom = DateTime.UtcNow.AddDays(-365),
    CreatedTo = DateTime.UtcNow
};
var orderSearchService = ServiceLocator.Current.GetInstance<IOrderSearchService>();
var searchResult = orderSearchService.FindPurchaseOrders(orderFilter);
var orders = searchResult.Orders;
var totalRecords = searchResult.TotalRecords;
```
