Quick Reference

3 Operator Categories, 11 Total Operators

🔄

Comparison Operators (4)

Equal, NotEqual, In, NotIn

Defined for all types (int, string, DateTime, DateOnly). Service support varies — e.g. NotIn is not honoured for some string fields.

HTTP: ?BizEntityTypeID.equal=4

SDK: filter.BizEntityTypeID = new FilterField<int?> { Equal = 4 }

📊

Range Operators (4)

GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual

Work with numeric and date types only

HTTP: ?CreatedDate.greaterThan=2024-01-01

SDK: filter.CreatedDate = new FilterField<DateTime?> { GreaterThan = date }

🔤

Text Operators (3)

Contains, StartsWith, EndsWith

Work with string fields only (case-insensitive)

HTTP: ?AccountNumber.beginsWith=ACC-

SDK: filter.AccountNumber = new FilterField<string?> { StartsWith = "ACC-" }

All filtering happens server-side - only matching records are returned from the database.

Why This Matters

Server-side filtering returns only matching records from the database, reducing bandwidth and improving performance through optimized indexes. Never retrieve all records and filter client-side.

💡

The Filtering Principle

The 7G API performs filtering at the database layer before building responses. Specify filter criteria in your request (HTTP query string or SDK filter object), and only matching records are returned. Never retrieve everything and filter client-side.

How It Works:

  1. Client sends request with filter criteria
  2. API translates filters to SQL WHERE clauses
  3. Database executes query with optimized indexes
  4. API builds response containing ONLY matching records
  5. Client receives filtered results ready for use

Comparison Operators (4)

These operators work with all data types: integers, strings, dates.

Operator HTTP (camelCase) SDK (PascalCase) Description
Equal equal Equal Exact match
NotEqual notEqual NotEqual Exclude exact match
In in In Match any value in list
NotIn notIn NotIn Exclude all values in list

Examples:

json
# Equal
GET /BizEntity?BizEntityTypeID.equal=4

# In (multiple values - OR logic)
GET /BizEntity?BizEntityTypeID.in=1,2,4

# NotEqual (exclusion)
GET /BizTransaction?BizTransactionTypeID.notEqual=0

# NotIn (exclude multiple values)
GET /BizEntity?BizEntityTypeID.notIn=5,6,7

Multiple Ways to Use In and NotIn (SDK)

The SDK provides three equivalent syntax options for setting multi-value operators. Choose based on your preference:

json
// Explicit FilterField construction
var filter = new BizEntityFilter
{
    ProductID = 5,
    PageNumber = 1,
    PageSize = 25
};

// In operator
filter.BizEntityTypeID = new FilterField<int?> { In = new int?[] { 1, 2, 4 } };

// NotIn operator (numeric/date fields; not honoured for some string fields)
filter.AccountID = new FilterField<int?> { NotIn = new int?[] { 5, 6 } };

var response = await client.BizEntity.GetAsync(filter);

Which Method to Use?

  • Explicit FilterField: Clear and explicit — good for complex filters and one-shot construction
  • Extension Methods: Fluent API style (SetIn / SetNotIn) with params syntax — convenient for value types
  • Direct Assignment: Useful when you already have an IEnumerable<T?> — assign directly to .In / .NotIn

Note: There are no implicit conversions on FilterField<T> — always set operators explicitly via property assignment.

Range Operators (4)

These operators work with numeric and date types only.

Operator HTTP (camelCase) SDK (PascalCase) Description
GreaterThan greaterThan GreaterThan Value > threshold
GreaterThanOrEqual greaterThanOrEqual GreaterThanOrEqual Value >= threshold
LessThan lessThan LessThan Value < threshold
LessThanOrEqual lessThanOrEqual LessThanOrEqual Value <= threshold

Examples:

json
# Greater than (after date)
GET /BizEntity?CreatedDate.greaterThan=2024-01-01T00:00:00Z

# Less than or equal (up to date, inclusive)
GET /BizEntity?CreatedDate.lessThanOrEqual=2024-12-31T23:59:59Z

# Date range (combine greaterThanOrEqual + lessThanOrEqual)
GET /BizEntity?CreatedDate.greaterThanOrEqual=2024-01-01T00:00:00Z&CreatedDate.lessThanOrEqual=2024-12-31T23:59:59Z

# Date-only range on BizTransaction (DateOnly type)
GET /BizTransaction?TransactionDate.greaterThanOrEqual=2024-01-01&TransactionDate.lessThanOrEqual=2024-12-31

Text Operators (3)

These operators work with string fields only and are case-insensitive.

Operator HTTP (camelCase) SDK (PascalCase) Description
Contains contains Contains Substring match (case-insensitive)
StartsWith beginsWith StartsWith Prefix match (case-insensitive)
EndsWith endsWith EndsWith Suffix match (case-insensitive)

Examples:

json
# Contains (case-insensitive substring)
GET /BizEntity?AccountNumber.contains=SMSF

# beginsWith (prefix match)
GET /BizEntity?AccountNumber.beginsWith=7G-

# endsWith (suffix match)
GET /BizEntity?AccountNumber.endsWith=-2024

# Combine text operators with other filters
GET /BizEntity?AccountNumber.contains=Super&BizEntityTypeID.equal=4&AccountNumber.beginsWith=7G-

Performance Note

Text operators (especially Contains) scan string values and may be slower on very large datasets. Combine with other filters (like BizEntityTypeID) to narrow results before applying text searches.

🔀

HTTP vs SDK Syntax Comparison

Same operators, different expression syntax

HTTP: Query String Dot Notation

json
# Single filter
GET /BizEntity?BizEntityTypeID.equal=3

# Multiple filters (AND logic)
GET /BizEntity?BizEntityTypeID.equal=3&AccountNumber.contains=SMSF&CreatedDate.greaterThan=2024-01-01

# In operator (comma-separated values)
GET /BizEntity?BizEntityTypeID.in=2,3,4

SDK: FilterField<T> Objects

csharp
// Single filter
var filter = new BizEntityFilter
{
    BizEntityTypeID = new FilterField<int?> { Equal = 4 }
};

// Multiple filters (AND logic)
var filter = new BizEntityFilter
{
    BizEntityTypeID = new FilterField<int?> { Equal = 4 },
    AccountNumber = new FilterField<string?> { Contains = "SMSF" },
    CreatedDate = new FilterField<DateTime?> { GreaterThan = new DateTime(2024, 1, 1) }
};

// In operator (explicit)
var filter = new BizEntityFilter
{
    BizEntityTypeID = new FilterField<int?> { In = new int?[] { 1, 2, 4 } }
};

var response = await client.BizEntity.GetAsync(filter);

FilterField Syntax

The SDK does not define implicit conversions on FilterField<T>. Always set operators explicitly:

Single value: filter.BizEntityTypeID = new FilterField<int?> { Equal = 4 }

Multiple values (In): filter.BizEntityTypeID = new FilterField<int?> { In = new int?[] { 1, 2, 4 } }

Filter fields default to new() on the filter DTOs, so you can also assign operator properties directly (filter.BizEntityTypeID.Equal = 4) without instantiating a new wrapper.

🔗

Combining Filters (AND Logic)

Build complex queries with multiple conditions

Multiple filters on different fields use AND logic - all conditions must match.

Examples:

json
# Multiple filters combined with AND logic
GET /BizEntity?BizEntityTypeID.equal=3&AccountNumber.contains=SMSF&CreatedDate.greaterThan=2024-01-01T00:00:00Z

# Result: Investor entities (type 3) whose account number contains 'SMSF', created after Jan 1, 2024
# All three filters must match for a record to be included

Multiple Operators on Same Field:

json
# Range query on same field
GET /BizEntity?AccountID.greaterThan=1000&AccountID.lessThan=5000

# Result: Accounts with ID between 1001 and 4999

OR Logic with In Operator:

json
# OR logic using 'in' operator
GET /BizEntity?BizEntityTypeID.in=1,2,4

# Result: Entities where type is (Individual, Company, SMSF)

Logic Rules

  • AND logic - All filters must match for a record to be included
  • OR logic - Use the in (HTTP) or In (SDK) operator for a single field
  • Complex OR - Make multiple API calls and merge results client-side (API doesn't support OR across different fields)

Best Practices

Guidelines for effective server-side filtering

Recommended

  • Use server-side filtering instead of retrieving all records and filtering client-side
  • Combine multiple filters for precise queries (AND logic automatically applied)
  • Use in operator for OR logic on a single field (e.g., BizEntityTypeID.in=1,2,4)
  • Leverage exact matches (equal) when possible for best performance
  • Filter by type/status FIRST, then add text searches to reduce dataset before substring matching
  • Combine filtering with pagination to handle large result sets efficiently

Avoid

  • Retrieving thousands of records then filtering client-side (bandwidth waste)
  • Using Contains on large datasets without other filters (performance cost)
  • Multiple sequential requests when filters can be combined
  • Case-sensitive comparisons (all text operators are case-insensitive)
  • Building complex OR logic across different fields (API doesn't support - make multiple calls)

What's Next?

Continue your journey with these related concepts: