# The Top() Function

> One of the most popular queries against time series data is to locate the top N performing instruments. “Performing” could mean different conditions or aggregates. To meet this need for the C and C++ APIs, a `*_top()` function is generated for all sequence fields. In addition to the usual generated functions for classes, fields and indexes, for classes containing sequence one of more fields `mcocomp` generates function `classname_fieldname_top()`. This API allows applications to avoid writing a loop that scans all objects in a class and calculates the aggregate for each object. (Note that, since this function scans all objects in a class, it can be a time-consuming function call.)

> For scalar fields, the generated function prototype is:

>         MCO_RET classname_fieldname_top( mco_trans_h t, mco_cursor_h cursor, /*IN-OUT*/ 	mco_size_t* n,
>             /*OUT*/		<TYPE>* keys, /*OUT*/		double* aggregates,
>             MCO_RET (*aggregate)( mco_trans_h t, Security* handle, /*OUT*/	double* result, void* ctx),
>             MCO_RET (*filter)( mco_trans_h t, mco_cursor_h cursor, void* ctx),
>             void* ctx);

> The function arguments are as follows:

> t | The current transaction handle
> cursor | An open and non-empty cursor (it is assumed that the caller first check for status code `MCO_S_CURSOR_EMPTY`)
> n | IN: The maximum number of top results to be received; OUT: the actual number of top results
> keys | An array of size `n` for the top `n` values of `fieldname`
> aggregates | An array if size N for the top `n` aggregate values
> aggregate | A function performing aggregation of the sequence for the current record, which returns: `MCO_S_OK` for normal completion, `MCO_S_NOTFOUND` if the sequence is empty or for some reason the aggregation can not be performed and this object should be skipped, `MCO_E_*` (any other error code) in case of abnormal termination. This function has the following arguments:
> t | The current transaction handle
> handle | The address of an object handle for the current object
> result | The address of the aggregation result (must be of type `double`)
> ctx | The address of an optional user defined context passed to the `_top()` function
> filter | An optional filter function that checks if the current object satisfies query conditions. It is normally needed because an index search positions a cursor at the proper position but then it is possible to navigate in any direction to the end of the result set; calling this filter function is necessary to check that the query condition is still satisfied. If this parameter is `NULL`, then traversal is performed until the end of the cursor. The filter function returns: `MCO_S_OK` for normal completion, `MCO_S_NOTFOUND` if the sequence is empty or for some reason the aggregation can not be performed and this object should be skipped, `MCO_S_CURSOR_END` if there are no more records matching the query condition (so iteration should be stopped), `MCO_E_*` (any other error code) in case of abnormal termination. This function has the following arguments:
> t | The current transaction handle
> cursor | An open and non-empty cursor (it is assumed that the caller first check for status code `MCO_S_CURSOR_EMPTY`)
> ctx | The address of an optional user defined context passed to the `_top()` function
> ctx | The address of an optional user defined context

> For fixed-size character fields (`char, nchar and wchar`), the prototype is:

>         MCO_RET classname_fieldname_top( mco_trans_h t, mco_cursor_h cursor, /*IN-OUT*/ 	mco_size_t* n,
>             /*OUT*/		<TYPE> keys[][SIZE_OF_TYPE], /*OUT*/		double* aggregates,
>             MCO_RET (*aggregate)( mco_trans_h t, Security* handle, /*OUT*/	double* result, void* ctx),
>             MCO_RET (*filter)( mco_trans_h t, mco_cursor_h cursor, void* ctx),
>             void* ctx);

> Note that the prototype is the same as for scalar fields, except that the `keys` argument is a two dimensional array where the last dimension is equal to the size of type.

> For variable-length string fields `(string, nstring and wstring`), the prototype is:

>         MCO_RET classname_fieldname_top( mco_trans_h t, mco_cursor_h cursor, /*IN-OUT*/ 	mco_size_t* n,
>             /*OUT*/		<TYPE>** keys, uint2 max_key_len, <TYPE>* buf,
>             /*OUT*/		double* aggregates,
>             MCO_RET (*aggregate)( mco_trans_h t, Security* handle, /*OUT*/	double* result, void* ctx),
>             MCO_RET (*filter)( mco_trans_h t, mco_cursor_h cursor, void* ctx),
>             void* ctx);

> Note that the arguments are the same as for scalars except for the following:

> keys | An array of size `n` of pointers for the top `n` values of `fieldname`
> max_key_len | The maximum size of the field (larger values will be truncated)
> buf | The buffer of `n * max_key_len` size to hold the string bodies