Search for orders using OrderContext
Describes how to search for orders using OrderContext in Optimizely Commerce Connect 13.
This topic describes how to work with the order search API including:
- The capabilities and limitations of Optimizely Commerce Connect order search
- API classes and properties
- Code examples of different scenarios
- Description of the search stored procedure
Searching for orders is a common part of ecommerce solutions, such as integrating with ERPs and custom administrative interfaces where orders are exported, filtered, or edited. You often need to load orders based on submission date, status, or particular properties or meta-field properties of the order or cart, including properties of its child objects (for example, shipments or line items).
Classes in this topic are available in the Mediachase.Commerce.Orders
namespace.
Search pattern
The following pattern is the simplest way to execute order search in Optimizely Commerce Connect using the API.
Begin the search code with:
OrderSearchOptions searchOptions = new OrderSearchOptions();
searchOptions.StartingRecord = 0; //or whatever you want to specify for paging purposes
searchOptions.RecordsToRetrieve = 10000; //or whatever you want to specify for paging purposes searchOptions.Namespace = "Mediachase.Commerce.Orders";
Then continue with:
OrderSearchParameters parameters = new OrderSearchParameters();
//the following is for returns-only purchase orders... for shopping carts, specify ShoppingCart parameters.SqlMetaWhereClause = "";
searchOptions.Classes.Add("PurchaseOrder");
parameters.SqlWhereClause = sqlQuery.ToString();
//If you are searching for shopping carts (non serializable cart system), you can call the Search<Cart> method and return an array of Cart objects
PurchaseOrder[] purchaseOrderCollection = OrderContext.Current.Search<PurchaseOrder>(parameters, searchOptions);
The SQL query above is OrderGroupId IN (SELECT OrderGroupId FROM)
.
Use order search
The order search returns arrays of OrderGroup
objects: ShoppingCart
, PaymentPlan
, and PurchaseOrder
.
The order search is only intended to return shipments, line items, payment objects, or any other objects/data in the order. The Order Search API does not conduct an order search for those types of objects alone. The API lets you search for carts/orders/payment plans based on properties, including meta-fields associated with any of the objects in an OrderGroup and any outside database tables you may want to use for filtering/joins.
The search pattern implemented in the API has two parts:
- Get a list of
OrderGroupIds
as search results using the stored procedureecf\_OrderSearch
. Insert those values into a database tableOrderSearchResults
(with a GUID that separates it from other search results). This is the search phase, based on criteria passed to the search. - The
OrderGroupIds
are loaded fromOrderSearchResults
, and the corresponding array ofShoppingCart/PurchaseOrder/PaymentPlan
is loaded and returned.
Note
You can sort based on
OrderGroup
table fields only.
Primary classes and properties
Mediachase.Commerce.Orders.Search.OrderSearchOptions
This class lets you specify the number of records to return, if results are to be cached, the type of OrderGroup
data to be returned (for example, ShoppingCart/PurchaseOrder/PaymentPlan
), and the starting record number (for paging).
Properties
CacheResults
– This is inherited fromSearchOptions
but is not actually used by order search.RecordsToRetrieve
StartingRecord
– Integer. Use these fields to page search results.
Classes
StringCollection
– This lets you specify the order metadata object on which you want to create a subquery. For example, to find all shipments where a shipment meta-field value is a particular value, specify ShipmentEx for the classes property. This is a string collection. In most cases, only one class needs to be specified.
You can specify the following classes with the corresponding database table that is queried:
- CashCardPayment (OrderFormPayment_CashCard)
- CreditCardPayment (OrderFormPayment_CreditCard)
- ExchangePayment (OrderFormPayment_Exchange)
- GiftCardPayment (OrderFormPayment_GiftCard)
- InvoicePayment (OrderFormPayment_Invoice)
- LineItemEx (LineItemEx)
- OrderFormEx (OrderFormEx)
- OrderGroupAddressEx (OrderGroupAddressEx)
- OtherPayment (OrderFormPayment_Other)
- PaymentPlan (OrderGroup_PaymentPlan)
- PurchaseOrder (OrderGroup_PurchaseOrder)
- ShipmentEx (ShipmentEx)
- ShoppingCart (OrderGroup_ShoppingCart)
Note
You must specify at least one class, even if you don't specify a
SQLMetaWhereClause
in the parameters object. If you do not specifySQLMetaWhereClause
but specify anOrderGroup
(PurchaseOrder
,ShoppingCart
,PaymentPlan
), it filters the results for thatOrderGroup
type only.
Namespace
For order searches, this should always be Mediachase.Commerce.Orders
.
Mediachase.Commerce.Orders.Search.OrderSearchParameters
This class lets you specify where clauses necessary to narrow the order search.
Properties
OrderByClause
– This clause can use onlyOrderGroup
table fields. If this field is not set,OrderGroupId
is used.SqlMetaWhereClause
– This field matches up with theOrderSearchOptions.Classes
field to form a subquery based on anOrderGroup
metaclass. This clause looks like this:"META.CardType = 'Visa'"
(where the option classes collection contains"CreditCardPayment"
). That returns all orders/carts/payment plans with visa payments. META is the SQL alias for the table associated with the class you specify (see options Classes property above).SqlWhereClause
– A SQLWHERE
clause that lets you specify additional order search criteria to form a subquery in the search stored procedure (see the stored procedure breakdown later in this topic).
Using the META keyword here refers to a different alias than using it in the SqlMetaWhereClause
, where it is an alias for the table associated with the class specified in the options object. In the SQLWhereClause
, it refers to a table in memory that has two columns:
- Key – The
OrderGroupId
. - Rank – Part of the meta
WHERE
clause subquery. (You probably do not want to use META here.)
Only the OrderGroup
table is referenced directly in the SQL WHERE clause. So, you could have a clause like OrderGroupId IN (SELECT OrdergroupId FROM Shipment WHERE NOT ShipmentTrackingNumber IS NULL)
.
Note
You cannot add an
ORDER BY
clause here, because it is part of a subquery.
The following fields are not used for order search:
JoinSourceTable
JoinSourceTableKey
JoinTargetQuery
JoinTargetTableKey
JoinType
OrderByClause
– A SQL Order By
clause that you can order the record. You can use any column name of columns in OrderGroup
table, or META.<column-name>
for columns in the metaclass table. For example, OrderGroup\_PurchaseOrder
.
Mediachase.Commerce.Orders.OrderContext
This class is a singleton with several methods to find orders:
FindActiveOrders()
– Retrieves purchase orders where theOrderGroup.Status
is eitherInProgress
orPartiallyShipped
.Current.Search<Cart>()
– Finds shopping carts based on parameters and options specified with the two other classes.FindPaymentPlans()
– Finds payment plans based on parameters and options specified with the two other classes.FindPurchaseOrders()
– Finds purchase orders based on parameters and options specified with the two other classes.FindPurchaseOrdersByStatus()
– Finds orders with particular order statuses.
Code examples
The code is common and first defined for all of the following code examples.
OrderSearchOptions searchOptions = new OrderSearchOptions();
searchOptions.StartingRecord = 0;
searchOptions.RecordsToRetrieve = 10000;
searchOptions.Namespace = "Mediachase.Commerce.Orders";
The following examples have code that follows the code above.
Example 1
Retrieves purchase orders with a tracking number that is like a particular pattern and with a tracking number (a meta-field) assigned to at least one shipment in the purchase order.
OrderSearchParameters parameters = new OrderSearchParameters();
searchOptions.Classes.Add("PurchaseOrder");
parameters.SqlMetaWhereClause = "META.TrackingNumber LIKE '%PO%'";
parameters.SqlWhereClause = "OrderGroupId IN (SELECT OrdergroupId FROM Shipment WHERE NOT ShipmentTrackingNumber IS NULL)";
PurchaseOrder[] purchaseOrderCollection = SeOrderContext.Current.Search<PurchaseOrder>(parameters, searchOptions);
Example 2
Retrieves purchase orders that contain line items that have an RMANumber (a meta-field) associated with them.
OrderSearchParameters parameters = new OrderSearchParameters();
searchOptions.Classes.Add("LineItemEx");
parameters.SqlMetaWhereClause = "NOT META.RMANumber IS NULL";
parameters.SqlWhereClause = "OrderGroupId IN (Select ObjectId FROM OrderGroup_PurchaseOrder)";
PurchaseOrder[] purchaseOrderCollection = SeOrderContext.Current.Search<PurchaseOrder>(parameters, searchOptions);
Note
The
SQLWhereClause
is used to ensure that only purchase orders are returned. If you do not do this, you may get carts (or payment plans, if they exist in your system) also in the dataset, and you will get errors like: Index 0 is either negative or above rows count.
This is because the metadata object load is getting confused by the different metafields in a purchase order intead of a cart. If you query orders using the API and do not specify which OrderGroup
object as the metaclass, add this WHERE
filter in the SQLWhereClause
. You can make a compound WHERE
clause including this filter.
Example 3
Retrieves shopping carts where line items have an expiration date (a metafield) greater than a particular value.
OrderSearchParameters parameters = new OrderSearchParameters();
searchOptions.Classes.Add("LineItemEx");
parameters.SqlMetaWhereClause = "META.ExpirationDate > '1/1/2012'";
parameters.SqlWhereClause = "OrderGroupId IN (Select ObjectId FROM OrderGroup_ShoppingCart)";
Cart[] cartCollection = SeOrderContext.Current.Search<Cart>(parameters, searchOptions);
Example 4
Retrieves purchase orders that have shipments with a particular a shipping status (a meta-field).
OrderSearchParameters parameters = new OrderSearchParameters();
searchOptions.Classes.Add("ShipmentEx");
parameters.SqlMetaWhereClause = "NOT META.PrevStatus IS NULL";
parameters.SqlWhereClause = "OrderGroupId IN (Select ObjectId FROM OrderGroup_PurchaseOrder)";
PurchaseOrder[] purchaseOrderCollection = SeOrderContext.Current.Search<PurchaseOrder>(parameters, searchOptions);
Example 5
This is a more complex SQL where clause that returns all orders that contain SKUs whose name contains a substring by using a join with the CatalogEntry
table.
StringBuilder sqlQuery = new StringBuilder();
sqlQuery.Append("OrderGroupId IN (SELECT OrderGroupId From LineItem li ");
sqlQuery.Append("INNER JOIN CatalogEntry en ");
sqlQuery.Append("ON li.CatalogEntryId = en.Code ");
sqlQuery.Append("WHERE en.Name LIKE '%Wine%')");
OrderSearchParameters parameters = new OrderSearchParameters();
searchOptions.Classes.Add("PurchaseOrder"); parameters.SqlMetaWhereClause = "";
parameters.SqlWhereClause = sqlQuery.ToString();
PurchaseOrder[] purchaseOrderCollection = SearOrderContext.Current.Search<PurchaseOrder>(parameters, searchOptions);
Note
You do not have an
SqlMetaWhereClause
, but you must specify aPurchaseOrder
class.
You can add any subquery, allowing the most flexibility.
Example 6
Joins several order metadata tables in the SQL where clause. This is a better, easier way to do more complex order searches with multiple order metaclasses, rather than using the options Classes collection for filtering order metaclasses.
Note
The following query appears to have the potential to return duplicate ordergroupids, as an order can have multiple shipments or line items. However, the order search stored procedure ensures that only distinct order IDs are returned.
StringBuilder sqlQuery = new StringBuilder();
sqlQuery.Append("OrderGroupId IN (SELECT li.OrderGroupId From LineItem li ");
sqlQuery.Append("INNER JOIN LineItemEx ex ");
sqlQuery.Append("ON li.LineItemId = ex.ObjectId ");
sqlQuery.Append("INNER JOIN Shipment sh ");
sqlQuery.Append("ON li.OrderGroupId = sh.OrderGroupId ");
sqlQuery.Append("INNER JOIN ShipmentEx shex ");
sqlQuery.Append("ON sh.ShipmentId = shex.ObjectId ");
sqlQuery.Append("WHERE ex.ExpirationDate > '1/1/2011'");
sqlQuery.Append("AND NOT shex.PrevStatus IS NULL)");
OrderSearchParameters parameters = new OrderSearchParameters();
searchOptions.Classes.Add("PurchaseOrder");
parameters.SqlMetaWhereClause = "";
parameters.SqlWhereClause = sqlQuery.ToString();
PurchaseOrder[] purchaseOrderCollection = SeOrderContext.Current.Search<PurchaseOrder>(parameters, searchOptions);
Note
Always test queries in SQL Management Studio first, and remember the closing
)
for yourSqlWhereClause
property value.
Stored procedure breakdown
The first part of the order search performs a dynamic search for orders based on the OrderSearchParameters
and OrderSearchOption
properties set in code.
This is the final query built based on settings you specify. The stored procedure that uses these properties to create a list of order ids is ecf\_OrderSearch
.
declare @Page_temp table (TotalRecords int, OrderGroupId int);
with OrderedResults as
(SELECT count([OrderGroup].OrderGroupId)
OVER() TotalRecords, [OrderGroup].OrderGroupId, Rank, ROW_NUMBER()
OVER(ORDER BY ) RowNumber
FROM [OrderGroup] OrderGroup
INNER JOIN (select distinct U.[KEY], U.Rank from
(select 100 as 'Rank', META.ObjectId as 'Key',
* from <database table associated with the order metaclass in the options Classes property>
META WHERE <SQLMetaWhereClause>)
U) META
ON OrderGroup.[OrderGroupId] = META.[KEY]
(<SQLWhereClause>))
INSERT INTO @Page_temp (TotalRecords, OrderGroupId)
SELECT top(<RecordsToRetrieve>) TotalRecords, OrderGroupId FROM OrderedResults
WHERE RowNumber > <StartingRecord>;;
select @RecordCount = TotalRecords from @Page_temp;
INSERT INTO OrderSearchResults (SearchSetId, OrderGroupId)
SELECT [SearchSetId], OrderGroupId from @Page_temp;
Note
- The query for metadata is built using the class you specify and the
SQLMetaWhereClause
you specify (already mentioned above). The META where clause "inside" theSQLMetaWhereClause
is different from the META alias available to the SQLWhereClause.- If no
SQLWhereClause
is specified, the query executes without the *AND [SQLWhereClause]
portion. The same goes forSQLMetaWhereClause
.- The Application ID is managed internally by Optimizely Commerce Connect.
Updated 1 day ago