List Filters in ListOptions
Permission, Membership, Search & Joint Filters Without Joins. ListOptions in In addition to sorting, grouping, caching, and post-processing, ListOptions offer powerful filter features that let you filter the query with prefetched id lists.
1. Scope
ListOptions in Mindbricks define the behavior of list-type Business APIs (crudType = "list"). In addition to sorting, grouping, caching, and post-processing, ListOptions offer powerful filter features that let you:
Internally, Mindbricks does this by:
-
Running prefetch queries (to permissions, membership, Elasticsearch, or joined objects),
-
Producing ID lists of allowed (or disallowed) objects, and
-
Automatically merging these lists into the final DB query for the main object.
This pattern lets architects express complex access patterns and filters in a declarative, pattern-driven way, while Mindbricks takes care of generating efficient queries.
From the ontology, ListOptions are defined as:
"ListOptions": {
"listSortBy": ["SortByItem"],
"listGroupBy": ["PropRefer"],
"queryCache": "Boolean",
"setAsRead": ["DataMapItem"],
"permissionFilters": ["ListPermissionFilter"],
"membershipFilters": ["ListMembershipFilter"],
"searchFilter": "ListSearchFilter",
"jointFilters": "ListJointFilterSettings",
"__nullables": [
"listSortBy",
"listGroupBy",
"setAsRead",
"permissionFilter",
"membershipFilters",
"searchFilter",
"jointFilters"
]
}
This document focuses on the four filter-related features:
-
permissionFilters– object-based permission filters -
membershipFilters– membership-based filters -
searchFilter– full-text search using Elasticsearch -
jointFilters– join-like filters using secondary objects
2. Execution Flow: How List Filters Work
At a high level, when a list Business API runs, Mindbricks:
-
Reads parameters & builds the base
whereClause(fromWhereClauseSettings). -
Applies permission filters, if any.
-
Applies membership filters, if any.
-
Applies search filters, if any.
-
Applies joint filters, if any.
-
Merges these into a final ID-based filter (usually
id IN [...]or intersections/unions of ID sets). -
Executes the main DB query for the primary DataObject.
This means:
-
Filters are expressed at a semantic level (permissions, memberships, search, joins).
-
The generated code performs the heavy lifting: prefetching ID lists, combining them logically, and enforcing them in the final query.
3. Permission Filters – permissionFilters
Pattern: ListPermissionFilter
"ListPermissionFilter": {
"name": "String",
"condition": "MScript",
"permission": "String"
}
3.1 Concept
permissionFilters are used to enforce object-based permissions (OBAC) or global permission logic at the list level. Instead of returning all objects matching the base query, Mindbricks:
-
Resolves which objects the current user is allowed to see based on a named permission (e.g.,
"projectManagement.viewProject"). -
Builds an ID list of allowed objects.
-
Intersects that ID list with the main query.
Multiple permission filters can be defined. If more than one is present, all their constraints are applied (logical AND).
3.2 Fields
-
name– descriptive, code-safe name of the filter. -
permission– the permission string that must be satisfied. -
condition– an optional MScript boolean. If it evaluates tofalse, this permission filter is skipped.
3.3 Example
List projects where the user has "projectManagement.viewProject":
"listOptions": {
"permissionFilters": [
{
"name": "filterByProjectViewPermission",
"permission": "projectManagement.viewProject",
"condition": "true"
}
]
}
Super admins can bypass this filter:
"condition": "this.session.roleId !== 'superAdmin'"
4. Membership Filters – membershipFilters
Pattern: ListMembershipFilter
"ListMembershipFilter": {
"name": "String",
"dataObjectName": "DataObjectName",
"objectKeyIdField": "PropRefer",
"userKey": "MScript",
"checkFor": "MScript",
"condition": "MScript"
}
4.1 Concept
membershipFilters are used when access to a list of objects depends on membership in some membership object (e.g., projectMember, organizationMember).
The filter answers:
Internal behavior:
-
Prefetch membership records from the membership object.
-
Extract IDs of the target main objects.
-
Filter main list to those IDs.
-
If multiple membership filters exist, being valid in any of them is usually enough (logical OR at membership layer).
4.2 Fields
-
name– descriptive name for the filter. -
dataObjectName– the resource whose membership settings apply (e.g.,"project"). -
objectKeyIdField– which property of the list item holds the object ID (often"id"). -
userKey– MScript returning user ID, typically"this.session.userId". -
checkFor– optional MScript, for extra membership logic (role, status, etc.). -
condition– optional MScript that decides whether to apply this membership filter.
4.3 Example
List projects where the user is a member:
"listOptions": {
"membershipFilters": [
{
"name": "filterByProjectMembership",
"dataObjectName": "project",
"objectKeyIdField": "id",
"userKey": "this.session.userId",
"checkFor": "true",
"condition": "true"
}
]
}
Skip membership filter for SaaS-level admin:
"condition": "this.session.roleId !== 'superAdmin'"
5. Search Filter – searchFilter
Pattern: ListSearchFilter
"ListSearchFilter": {
"hasSearchFilter": "Boolean",
"condition": "MScript",
"keyword": "MScript",
"searchProperties": ["PropRefer"]
}
5.1 Concept
The searchFilter feature integrates full-text search by:
-
Performing a pre-search in Elasticsearch on the main object’s index using the given keyword and searchProperties.
-
Collecting the IDs of matching documents.
-
Limiting the main DB query to those IDs.
This mimics a full-text search + DB intersection, but:
-
Without writing raw ES queries.
-
Without altering your DataObject design (as long as ES indexing is enabled).
5.2 Fields
-
hasSearchFilter– turns the search filter on. -
condition– optional MScript; if false, skip the search filter. -
keyword– MScript that returns the search keyword (e.g.,this.keyword). -
searchProperties– list of fields on the main object to search against.
5.3 Example
Search users by name or email:
"listOptions": {
"searchFilter": {
"hasSearchFilter": true,
"condition": "!!this.keyword",
"keyword": "this.keyword",
"searchProperties": ["fullname", "email"]
}
}
This will:
-
Use the
usersES index. -
Perform a search across
fullnameandemail. -
Get matching IDs.
-
Filter the SQL/Mongo query to those IDs.
6. Joint Filters – jointFilters (ListJointFilterSettings & ListJointFilter)
Patterns: ListJointFilterSettings, FilterOperator, ListJointFilter
"ListJointFilterSettings": {
"operator": "FilterOperator",
"filters": ["ListJointFilter"]
}
"FilterOperator": ["AND", "OR"]
"ListJointFilter": {
"name": "String",
"condition": "MScript",
"joinedDataObject": "DataObjectName",
"whereClause": "MScript"
}
6.1 Concept
jointFilters are like lightweight, prefetch-based joins:
Instead of defining a relational join directly, Mindbricks:
-
Runs a separate query on the
joinedDataObjectusing an MScript whereClause. -
Produces an ID list (IDs of the main object associated with matched joined objects).
-
Applies that ID list as a filter on the main list.
Multiple joint filters can be combined with:
-
"AND"– main objects must satisfy all joint filters. -
"OR"– main objects must satisfy at least one joint filter.
6.2 Fields
-
ListJointFilterSettings.operator–"AND"or"OR"; how to combine multiple joint filters. -
ListJointFilter.name– descriptive name. -
joinedDataObject– the secondary object you join with (e.g.,invoice,subscription,projectMemberwhere parent is another object). -
whereClause– MScript Query that selects the matching joined objects. -
condition– optional MScript to decide whether to apply a specific joint filter.
The relationship between the main object and joinedDataObject must be defined via relations (PropertyRelation) so Mindbricks knows how to map IDs.
6.3 Example: Filter Users by Active Subscription
Imagine:
-
Main object:
user -
Joined object:
subscriptionwithsubscription.userIdreferencinguser.id -
You want to list only users with active subscriptions.
"listOptions": {
"jointFilters": {
"operator": "AND",
"filters": [
{
"name": "hasActiveSubscription",
"joinedDataObject": "subscription",
"whereClause": "{ status: { "$eq": 'active' } }",
"condition": "true"
}
]
}
}
Mindbricks will:
-
Query
subscriptionfor rows wherestatus = 'active'. -
Collect distinct
userId. -
Filter the
userlist toid IN [those userIds].
6.4 Example: Combine Multiple Joint Filters with OR
List users who either:
-
Have an active subscription OR
-
Have at least one open support ticket.
"listOptions": {
"jointFilters": {
"operator": "OR",
"filters": [
{
"name": "hasActiveSubscription",
"joinedDataObject": "subscription",
"whereClause": "{ status: { "$eq": 'active' } }"
},
{
"name": "hasOpenTicket",
"joinedDataObject": "supportTicket",
"whereClause": "{ status: { "$eq": 'open' } }"
}
]
}
}
7. Combining Filters: Permission + Membership + Search + Joint
All four filter families can coexist in a single ListOptions:
"listOptions": {
"permissionFilters": [ ... ],
"membershipFilters": [ ... ],
"searchFilter": { ... },
"jointFilters": { ... }
}
The overall logic (simplified) looks like:
BaseWhereClause
AND objectId IN PermissionFilterIds (if any)
AND objectId IN MembershipFilterIds (if any)
AND objectId IN SearchFilterIds (if any)
AND (JointFilterIds1 AND/OR JointFilterIds2 ...)
This gives you:
-
Permission-aware lists
-
Membership-aware lists
-
Searchable lists
-
Join-like behavior based on secondary objects
…all without writing:
-
Raw SQL joins
-
Raw ES queries (except in advanced scenarios)
-
Custom repository methods
Mindbricks composes these filters into optimized queries for the underlying database and Elasticsearch.
8. Best Practices
-
Start Simple
-
Use
searchFilterfor text search. -
Use
membershipFiltersfor resource membership. -
Use
permissionFiltersfor object-level PBAC.
-
-
Use**
jointFilters**** When You Need Join-Like Filtering**- E.g., “users with at least one active subscription”, “projects with open tasks”, “orders with unpaid invoices”.
-
Keep Conditions Explicit
- Use
conditionfields to skip filters for admins, support, or specific scenarios.
- Use
-
Leverage MScript Query Syntax
-
All
whereClausefields use the MScript Query syntax you already use inWhereClauseSettings. -
Reuse library functions for complex queries.
-
-
Measure & Adjust
-
For large datasets, joint filters and search filters may be expensive.
-
Consider using BFF DataViews & stored ES views for heavy read scenarios.
-
9. Summary
The filter features in ListOptions turn list APIs into powerful, declarative query engines:
-
permissionFilters– enforce object-level permissions. -
membershipFilters– filter by membership across resource objects. -
searchFilter– integrate full-text search into list APIs. -
jointFilters– emulate joins via prefetch ID lists and MScript queries.
All of this is done:
-
Without manual joins
-
Without custom repository functions
-
With full pattern-based control
As an architect, you describe what you want semantically (permissions, membership, search, joint conditions), and Mindbricks generates the how—efficient queries with automatic ID-list prefetching and merging.
This is one of the key features that makes Mindbricks list APIs expressive, secure, and scalable, while keeping your designs clear, maintainable, and AI-friendly.
Last updated Dec 29, 2025