---
source_url: https://www.pubnub.com/docs/data-storage/metadata/filtering
title: App Context filtering
updated_at: 2026-09-30T07:20:08.000Z
---

# App Context filtering

## Documentation index

To discover more PubNub resources:

1. Fetch [PubNub's llms.txt](https://www.pubnub.com/llms-full.txt) for a list of available pages in Markdown format.
2. Identify relevant URLs from that index.
3. Fetch the target pages.

Do not assume a path exists, always check the index first.

:::note Starting a new app? Use DataSync
[DataSync](https://www.pubnub.com/docs/data-storage/structured-data/overview.md) is the successor to App Context. It does everything App Context does for users, channels, and memberships, and adds typed schemas, partial updates with ETags, field-level access control, and per-class expiry. Refer to [How DataSync compares to App Context](https://www.pubnub.com/docs/data-storage/structured-data/overview.md) for a feature-by-feature comparison.
DataSync is currently available to new accounts and to accounts that are not actively using App Context. If your keysets already use App Context, keep using it for now. App Context remains fully supported and these pages stay accurate.
:::

An App Context filter expression is the string a `filter` parameter accepts on an [App Context](https://www.pubnub.com/docs/data-storage/metadata/overview.md) call, so PubNub returns only the records that match instead of every one. This reference covers which fields you can filter for each entity, every operator, and the exact syntax. Filtering requires [App Context enabled on your keyset](https://www.pubnub.com/docs/data-storage/metadata/overview.md#turn-on-app-context-and-configure-it).

```text
name LIKE "John*" && status == "active"
```

This expression matches only records whose `name` starts with `John` and whose `status` is `active`.

:::note Filter without writing code
BizOps Workspace applies this same filter language through a UI, no SDK required. In the [Admin Portal](https://admin.pubnub.com/), use **BizOps Workspace → User Management** to filter users and their channel memberships. Use **BizOps Workspace → Channel Management** to filter channels and their user members. Each exposes the fields and operators below through a **Filters** button instead of a `filter` parameter.
:::

This is a different language from [subscribe filter expressions](https://www.pubnub.com/docs/pub-sub/subscribe/subscribe-filter-expressions.md), which filter messages on the server before delivery and support different operators such as `CONTAINS` and arithmetic. Don't mix the two.

## Where filter applies

Which calls accept `filter` depends on the entity:

| Entity | Calls that accept `filter` |
| --- | --- |
| User metadata | The paginated "get all" call only |
| Channel metadata | The paginated "get all" call only |
| Membership (user → channels) | `getMemberships`, `setMemberships`, `removeMemberships`, and `manageMemberships` |
| Members (channel → users) | `getChannelMembers`, `setChannelMembers`, `removeChannelMembers`, and `manageChannelMembers` |

A single user or channel metadata record has no need for a filter, so `get`, `set`, and `remove` on one user or one channel don't accept it. Membership and member calls all return a list, even a write call such as `setChannelMembers`, so all four accept `filter` there. On a write call, the filter narrows which of the affected records come back in the response. It doesn't change which records get written or removed.

## Fields you can filter

### User fields

| Field | Description |
| --- | --- |
| `id` | The [User ID](https://www.pubnub.com/docs/architecture/core-concepts.md#user-id) |
| `name` | The user's display name |
| `externalId` | An identifier linking the user to an external system |
| `profileUrl` | URL to the user's profile picture |
| `email` | The user's email address |
| `status` | The condition the user is in, such as `active` |
| `type` | A category used to classify the user, such as `SupportAgent` |
| `updated` | Timestamp of the last update to the user's metadata |
| `custom` | Any field inside the user's `custom` object |

### Channel fields

| Field | Description |
| --- | --- |
| `id` | The channel name |
| `name` | The channel's display name |
| `description` | The channel's description |
| `status` | The condition the channel is in, such as `archived` |
| `type` | A category used to classify the channel, such as `OffTopic` |
| `updated` | Timestamp of the last update to the channel's metadata |
| `custom` | Any field inside the channel's `custom` object |

Not every SDK exposes `status` and `type` as filterable on user and channel metadata. Check your platform's API reference in [Available SDKs](https://www.pubnub.com/docs/sdks.md) before relying on either.

### Membership and member fields

A [membership](https://www.pubnub.com/docs/data-storage/metadata/overview.md#membership-connects-users-and-channels) call and a members call read the same underlying record from opposite directions. Each accepts a different field prefix for the side it isn't querying by ID:

| Call direction | Prefix for the other side | Common fields (no prefix) |
| --- | --- | --- |
| Memberships (`getMemberships`, `setMemberships`, and so on) | `channel.*` | `status`, `type`, `custom` |
| Members (`getChannelMembers`, `setChannelMembers`, and so on) | `uuid.*` | `status`, `type`, `custom` |

A memberships call rejects `uuid.*` fields, and a members call rejects `channel.*` fields. `type` on the common fields is only filterable through the REST API, not every SDK. The `uuid` prefix refers to the same entity as a [User ID](https://www.pubnub.com/docs/architecture/core-concepts.md#user-id). Refer to [Why type says uuid](https://www.pubnub.com/docs/data-storage/metadata/events.md#why-type-says-uuid) for why the field carries that name.

| `channel.*` field (memberships only) | `uuid.*` field (members only) |
| --- | --- |
| `channel.id` | `uuid.id` |
| `channel.name` | `uuid.name` |
| `channel.description` | `uuid.externalId` |
| `channel.status` | `uuid.profileUrl` |
| `channel.type` | `uuid.email` |
| `channel.updated` | `uuid.status` |
| `channel.custom` | `uuid.type` |
|  | `uuid.updated` |
|  | `uuid.custom` |

Filtering through a `custom` field, on any entity, isn't recommended. Refer to [Prefer exact matches over pattern and custom-field filters](#prefer-exact-matches-over-pattern-and-custom-field-filters).

## Operators

| Category | Operators | Example |
| --- | --- | --- |
| Comparison | `==`, `!=`, `<`, `>`, `<=`, `>=` | `status == "active"`, `updated >= "2024-01-01T00:00:00Z"` |
| Logical | `&&`, `||`, unary `!` | `status == "active" && type == "member"`, `!(status == "inactive")` |
| Pattern | `LIKE` | `name LIKE "John*"` |

Group a compound expression with parentheses instead of relying on evaluation order, so it reads correctly and stays correct if a clause is added later:

```text
(channel.type == "private" || channel.type == "restricted") && status == "active"
```

## Pattern matching with LIKE

`LIKE` matches a string against a wildcard pattern, where `*` stands for zero or more characters and can appear at the start, the end, or both:

```text
name LIKE "John*"              // starts with "John"
name LIKE "*Smith"              // ends with "Smith"
description LIKE "*support*"    // contains "support"
```

Escape a literal `*` in the pattern with a backslash:

```text
name LIKE "*\**"    // matches a name that contains a literal asterisk
```

## Data types

| Type | Syntax | Example |
| --- | --- | --- |
| String | Enclosed in double quotes | `name == "Alice"` |
| Number | Unquoted integer, decimal, or scientific notation, inside a `custom` field | `custom.score > 100` |
| Boolean | `true` or `false`, inside a `custom` field | `custom.public == true` |
| Null | `null` | `description == null` |
| Timestamp | An ISO 8601 string, compared like any other string | `updated >= "2024-01-01T00:00:00Z"` |

Escape a double quote inside a string value with a backslash:

```text
description == "Say \"hi\" to the team"
```

When you write the expression inside your own language's string literal, you may need a second layer of escaping for that language's own quote character. Check your SDK's API reference in [Available SDKs](https://www.pubnub.com/docs/sdks.md) for its convention.

## Null and custom fields

An object that has no referenced `custom` property is excluded from a comparison, regardless of the operator. Use `null` when you need to test whether a property exists:

```text
custom.label == null    // matches records without custom.label
custom.label != null    // matches records with custom.label
```

The value in a `custom` comparison must have the same type as the stored property. For example, if `custom.score` is a number, compare it to `100`, not `"100"`. Comparing different types is an error.

## Identifiers and property access

| Form | Use it for | Example |
| --- | --- | --- |
| Identifier | A field name that starts with a letter, `$`, or `_`, followed by letters, digits, `$`, or `_` | `name`, `$userID`, `_internal_flag` |
| Bracket notation | A field name with characters an identifier can't contain, such as a hyphen or a space | `custom["employment-status"] == "valid"` |
| Property path | A nested field on a membership or member, using dot notation | `channel.custom.team == "alpha"`, `uuid.custom.role == "moderator"` |

`custom.employment-status == "valid"` is invalid. The hyphen isn't allowed in an identifier. Use `custom["employment-status"]` instead.

## REST query encoding

When you call the REST API directly, URL-encode the entire filter expression in the query string. For example, encode `custom.public == true` as `custom.public%20%3D%3D%20true`. SDKs take the unencoded filter expression as a method parameter.

## Prefer exact matches over pattern and custom-field filters

For an application with many users, channels, or memberships, filter on exact ID equality, such as `id == "channel-123"`, rather than on `LIKE` pattern matching or a `custom` field. An exact-match filter on `id` uses a database index, while a pattern match or a `custom` field lookup scans every record. This is why filtering through `custom` isn't recommended for any entity.

The same rule applies in BizOps Workspace. The quick search box runs a `contains` search across every record. The **Filters** button with an `equals` condition on `id` uses the index instead, so prefer it for a large number of records.

## Use a filter in an SDK call

Every SDK's method signature takes the same filter string. Only the parameter name and call shape differ. The following filters both a user list and a channel list by name, using the PHP SDK's `filter()` method:

```php
// Filter users by custom field (note: filtering by custom properties may have limitations)
$filteredUsersResult = $pubnub->getAllUuidMetadata()
    ->includeFields(['customFields' => true])
    ->filter("name LIKE '*Alice*'")
    ->sync();

echo "Filtered users (name contains 'Alice'): " . count($filteredUsersResult->getData()) . "\n";

// Filter channels by name
$filteredChannelsResult = $pubnub->getAllChannelMetadata()
    ->includeFields(['customFields' => true])
    ->filter("name LIKE '*General*'")
    ->sync();

echo "Filtered channels (name contains 'General'): " . count($filteredChannelsResult->getData()) . "\n";
```

Check the API reference for your platform in [Available SDKs](https://www.pubnub.com/docs/sdks.md) for the exact parameter name and call shape.

## Next steps

* [App Context](https://www.pubnub.com/docs/data-storage/metadata/overview.md). The three entity types, how to turn on App Context, and where filtering fits among the other operations.
* [Get metadata for all users](https://www.pubnub.com/docs/data-storage/metadata/get-metadata-for-all-users.md). Page through user metadata and apply a filter.
* [Get metadata for all channels](https://www.pubnub.com/docs/data-storage/metadata/get-metadata-for-all-channels.md). Page through channel metadata and apply a filter.
* [Set, get, and remove memberships](https://www.pubnub.com/docs/data-storage/metadata/manage-memberships.md). Filter a user's channel list.
* [Set, get, and remove members](https://www.pubnub.com/docs/data-storage/metadata/manage-members.md). Filter a channel's user roster.
* [User Management](https://www.pubnub.com/docs/data-storage/metadata/manage-user-metadata.md). Filter users and memberships without code.
* [Channel Management](https://www.pubnub.com/docs/data-storage/metadata/manage-channel-metadata.md). Filter channels and members without code.
* [Subscribe filter expressions](https://www.pubnub.com/docs/pub-sub/subscribe/subscribe-filter-expressions.md). The unrelated server-side language that filters messages before delivery.

Last updated at: 2026-09-30T07:20:08.000Z
