# CDF Instance Filter Syntax

Filters are JSON objects passed to `list_instances`, `search_instances`, and `aggregate_instances`.

## Property references

View properties use a 3-element array: `[viewSpace, viewExternalId/viewVersion, propertyName]`.

Node built-in properties use: `["node", propertyName]`
Available: space, externalId, version, type, createdTime, lastUpdatedTime, deletedTime

Edge built-in properties use: `["edge", propertyName]`
Available: space, externalId, version, type, startNode, endNode, createdTime, lastUpdatedTime, deletedTime

## Basic Filters

### Equals
```json
{
  "equals": {
    "property": ["mySpace", "MyView/v1", "status"],
    "value": "Active"
  }
}
```

### In (match any of several values)
```json
{
  "in": {
    "property": ["mySpace", "MyView/v1", "status"],
    "values": ["Active", "Planned"]
  }
}
```

### Range (gt, gte, lt, lte)
```json
{
  "range": {
    "property": ["mySpace", "MyView/v1", "priority"],
    "gte": 1,
    "lte": 5
  }
}
```

### Prefix
```json
{
  "prefix": {
    "property": ["mySpace", "MyView/v1", "name"],
    "value": "Pump"
  }
}
```

### Exists (property is not null)
```json
{
  "exists": {
    "property": ["mySpace", "MyView/v1", "endTime"]
  }
}
```

### Direct Relation (filtering on a reference/relation property)

Direct relation properties point to other nodes. Use a dict with "space" and
"externalId" as the value:
```json
{
  "equals": {
    "property": ["mySpace", "MyView/v1", "asset"],
    "value": {"space": "targetSpace", "externalId": "targetExternalId"}
  }
}
```

To match any of several related nodes:
```json
{
  "in": {
    "property": ["mySpace", "MyView/v1", "asset"],
    "values": [
      {"space": "s1", "externalId": "asset1"},
      {"space": "s1", "externalId": "asset2"}
    ]
  }
}
```

### ContainsAny / ContainsAll (for list properties)
```json
{
  "containsAny": {
    "property": ["mySpace", "MyView/v1", "tags"],
    "values": ["critical", "safety"]
  }
}
```

## Combining Filters

### And
```json
{
  "and": [
    {"equals": {"property": ["mySpace", "MyView/v1", "status"], "value": "Active"}},
    {"range": {"property": ["mySpace", "MyView/v1", "priority"], "gte": 3}}
  ]
}
```

### Or
```json
{
  "or": [
    {"equals": {"property": ["mySpace", "MyView/v1", "status"], "value": "Active"}},
    {"equals": {"property": ["mySpace", "MyView/v1", "status"], "value": "Planned"}}
  ]
}
```

### Not
```json
{
  "not": {
    "equals": {"property": ["mySpace", "MyView/v1", "status"], "value": "Cancelled"}
  }
}
```

## Nested Filters (filtering on related instances)

Use `hasData` to filter on instances that have data in a specific view:
```json
{
  "hasData": [{"space": "mySpace", "externalId": "MyView", "version": "v1", "type": "view"}]
}
```

## Notes

- String comparisons are case-sensitive
- Timestamps use ISO 8601 format: `"2024-01-15T00:00:00Z"`
- `null` values can be checked with `exists` / `not exists`
- Instance space filtering is automatically applied by the server
