> For the complete documentation index, see [llms.txt](https://docs.pyck.cloud/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pyck.cloud/graphql-api/inputs/where-inputs.md).

# Where Inputs

Input types for filtering objects in GraphQL queries, providing comprehensive filtering capabilities across all pyck entities.

Audience: Programmer

WhereInput types are GraphQL input types used for filtering objects in queries. They provide a comprehensive set of predicates for filtering entities based on various criteria, including field comparisons, logical operations, and relationship filtering.

## Common Structure

All WhereInput types in pyck follow a consistent structure with the following components:

### Logical Operators

Every WhereInput type includes these logical operators:

| Field | Type                  | Description                                    |
| ----- | --------------------- | ---------------------------------------------- |
| `not` | `<Type>WhereInput`    | Negates the provided conditions                |
| `and` | `[<Type>WhereInput!]` | All conditions must match (logical AND)        |
| `or`  | `[<Type>WhereInput!]` | At least one condition must match (logical OR) |

### Field Predicates

For each field in the entity, WhereInput provides various comparison operators:

#### Basic Comparisons

* `field`: Equal to value
* `fieldNEQ`: Not equal to value
* `fieldIn`: Value is in the provided list
* `fieldNotIn`: Value is not in the provided list

#### Ordering Comparisons

* `fieldGT`: Greater than value
* `fieldGTE`: Greater than or equal to value
* `fieldLT`: Less than value
* `fieldLTE`: Less than or equal to value

#### String-Specific Operations

* `fieldContains`: String contains substring
* `fieldHasPrefix`: String starts with prefix
* `fieldHasSuffix`: String ends with suffix
* `fieldEqualFold`: Case-insensitive equality
* `fieldContainsFold`: Case-insensitive contains

#### Null Checks

* `fieldIsNil`: Field is null
* `fieldNotNil`: Field is not null

### Relationship Filtering

For entities with relationships, WhereInput types provide:

* `hasRelationship`: Boolean indicating if the relationship exists
* `hasRelationshipWith`: Array of related entity WhereInput for complex filtering

### Data Field Operations

For entities with JSON data fields, pyck provides powerful query operations:

* `Data`: Match exact value at JSON path - `Data: ["path", "value"]`
* `DataHasKey`: Check if key exists at path - `DataHasKey: "path"`
* `DataIn`: Value at path is in list - `DataIn: ["path", "value1", "value2"]`
* `DataContains`: String at path contains substring - `DataContains: ["path", "substring"]`

**Note**: Data field operations are available for most WhereInput types but not for `WorkflowSignalWhereInput`.

**Example**: Find customers with name "Max" in their data field:

```graphql
query {
  customers(where: {
    Data: ["name", "Max"]
  }) {
    edges {
      node {
        id
        data
      }
    }
  }
}
```

For comprehensive JSON field query documentation, see [JSON Field Queries](https://github.com/pyck-ai/docs/blob/main/graphql/advanced/json-field-queries.md).

## Available WhereInput Types

The following WhereInput types are available in the pyck GraphQL API:

| Type                             | Description                               |
| -------------------------------- | ----------------------------------------- |
| `AttachmentWhereInput`           | Filtering for file attachments            |
| `CompanyWhereInput`              | Filtering for company entities            |
| `CustomerWhereInput`             | Filtering for customer records            |
| `DataTypeWhereInput`             | Filtering for data type definitions       |
| `EventWhereInput`                | Filtering for system events               |
| `FileWhereInput`                 | Filtering for file records                |
| `InventoryCollectionWhereInput`  | Filtering for inventory collections       |
| `InventoryItemSetWhereInput`     | Filtering for inventory item sets         |
| `InventoryItemWhereInput`        | Filtering for inventory items             |
| `ItemMovementWhereInput`         | Filtering for item movements              |
| `PickingOrderItemWhereInput`     | Filtering for picking order items         |
| `PickingOrderWhereInput`         | Filtering for picking orders              |
| `ReceivingInboundItemWhereInput` | Filtering for receiving inbound items     |
| `ReceivingInboundWhereInput`     | Filtering for receiving inbound records   |
| `RepositoryMovementWhereInput`   | Filtering for repository movements        |
| `RepositoryWhereInput`           | Filtering for repository/location records |
| `StockWhereInput`                | Filtering for stock records               |
| `SupplierWhereInput`             | Filtering for supplier records            |
| `TransactionWhereInput`          | Filtering for transaction records         |
| `UserWhereInput`                 | Filtering for user accounts               |
| `WorkflowSignalWhereInput`       | Filtering for workflow signals            |
| `WorkflowWhereInput`             | Filtering for workflow records            |

## Usage Examples

### Basic Filtering

```graphql
query {
  inventoryItems(
    where: {
      sku: "PHONE-001"
    }
  ) {
    edges {
      node {
        id
        sku
        data
      }
    }
  }
}
```

### Logical Operations

```graphql
query {
  inventoryItems(
    where: {
      and: [
        { skuContainsFold: "PHONE" },
        { createdAtGTE: "2023-05-01T00:00:00Z" }
      ]
    }
  ) {
    edges {
      node {
        id
        sku
        createdAt
      }
    }
  }
}
```

### Complex Filtering with OR

```graphql
query {
  inventoryItems(
    where: {
      or: [
        { skuContains: "PHONE" },
        { skuContains: "TABLET" }
      ]
    }
  ) {
    edges {
      node {
        id
        sku
      }
    }
  }
}
```

### Negation

```graphql
query {
  inventoryItems(
    where: {
      not: {
        skuContains: "DISCONTINUED"
      }
    }
  ) {
    edges {
      node {
        id
        sku
      }
    }
  }
}
```

### Relationship Filtering

```graphql
query {
  inventoryItems(
    where: {
      hasItemstockWith: [
        {
          and: [
            { quantityGT: 0 },
            { repositoryID: "warehouse-main" }
          ]
        }
      ]
    }
  ) {
    edges {
      node {
        id
        sku
        itemstock {
          quantity
          repositoryID
        }
      }
    }
  }
}
```

### Data Field Filtering

```graphql
query {
  inventoryItems(
    where: {
      and: [
        { Data: ["color", "size"] },
        { DataContains: ["red", "large"] }
      ]
    }
  ) {
    edges {
      node {
        id
        sku
        data
      }
    }
  }
}
```

### String Filtering

```graphql
query {
  customers(
    where: {
      and: [
        { nameHasPrefix: "Acme" },
        { emailContainsFold: "@company.com" }
      ]
    }
  ) {
    edges {
      node {
        id
        name
        email
      }
    }
  }
}
```

### Date Range Filtering

```graphql
query {
  transactions(
    where: {
      and: [
        { createdAtGTE: "2023-01-01T00:00:00Z" },
        { createdAtLT: "2023-02-01T00:00:00Z" }
      ]
    }
  ) {
    edges {
      node {
        id
        createdAt
        type
      }
    }
  }
}
```

### Null Checks

```graphql
query {
  inventoryItems(
    where: {
      and: [
        { dataTypeIDNotNil: true },
        { descriptionIsNil: false }
      ]
    }
  ) {
    edges {
      node {
        id
        sku
        dataTypeID
        description
      }
    }
  }
}
```

## JavaScript Usage

When using the GraphQL API from JavaScript, WhereInput objects can be constructed as regular objects:

```javascript
const whereInput = {
  and: [
    { skuContainsFold: searchTerm },
    { createdAtGTE: startDate.toISOString() },
    {
      hasItemstockWith: [
        { quantityGT: 0 }
      ]
    }
  ]
};

const query = `
  query GetFilteredItems($where: InventoryItemWhereInput) {
    inventoryItems(where: $where) {
      edges {
        node {
          id
          sku
          createdAt
        }
      }
    }
  }
`;

const result = await client.query({
  query,
  variables: { where: whereInput }
});
```

## Best Practices

1. **Use specific field predicates**: Instead of loading all data and filtering client-side, use WhereInput to filter at the database level for better performance.
2. **Combine logical operators**: Use `and`, `or`, and `not` to create complex filtering conditions that match your business logic.
3. **Leverage relationship filtering**: Use `has...With` predicates to filter based on related entity properties without separate queries.
4. **Case-insensitive searching**: Use `*EqualFold` and `*ContainsFold` predicates for user-friendly search functionality.
5. **Date range queries**: Combine `*GTE` and `*LT` predicates for effective date range filtering.
6. **Null safety**: Use `*IsNil` and `*NotNil` predicates to handle optional fields properly.
7. **Index-friendly queries**: Structure your where conditions to leverage database indexes for optimal performance.

## RepositoryWhereInput Breaking Changes

The `RepositoryWhereInput` type has been updated with the following breaking changes:

### Removed Fields

The following parentID comparison filters have been removed because parentID is now an edge reference (ID type) instead of a UUID:

* `parentIDGT` - Greater than comparison (removed)
* `parentIDGTE` - Greater than or equal comparison (removed)
* `parentIDLT` - Less than comparison (removed)
* `parentIDLTE` - Less than or equal comparison (removed)

### Changed Fields

The following parentID fields now use `ID` type instead of `UUID`:

| Field           | Old Type  | New Type |
| --------------- | --------- | -------- |
| `parentID`      | `UUID`    | `ID`     |
| `parentIDNEQ`   | `UUID`    | `ID`     |
| `parentIDIn`    | `[UUID!]` | `[ID!]`  |
| `parentIDNotIn` | `[UUID!]` | `[ID!]`  |

### New Edge Predicates

New edge predicates have been added for filtering repositories based on parent/child relationships:

| Field             | Type                      | Description                                                   |
| ----------------- | ------------------------- | ------------------------------------------------------------- |
| `hasParent`       | `Boolean`                 | Filter repositories that have (or don't have) a parent        |
| `hasParentWith`   | `[RepositoryWhereInput!]` | Filter repositories whose parent matches the given conditions |
| `hasChildren`     | `Boolean`                 | Filter repositories that have (or don't have) children        |
| `hasChildrenWith` | `[RepositoryWhereInput!]` | Filter repositories whose children match the given conditions |

### Migration Examples

**Before (finding root repositories):**

```graphql
query {
  repositories(where: { parentIDIsNil: true }) {
    edges { node { id name } }
  }
}
```

**After (finding root repositories):**

```graphql
query {
  repositories(where: { hasParent: false }) {
    edges { node { id name } }
  }
}
```

**Before (filtering by parent):**

```graphql
query {
  repositories(where: { parentID: "uuid-here" }) {
    edges { node { id name } }
  }
}
```

**After (filtering by parent with conditions):**

```graphql
query {
  repositories(
    where: {
      hasParentWith: [{ name: "Main Warehouse" }]
    }
  ) {
    edges { node { id name } }
  }
}
```

**Finding repositories with children:**

```graphql
query {
  repositories(
    where: {
      hasChildren: true,
      hasChildrenWith: [{ type: static }]
    }
  ) {
    edges {
      node {
        id
        name
        children { id name }
      }
    }
  }
}
```

## FileWhereInput

`FileWhereInput` provides predicates for every persisted field on the `File` entity. The full set of standard predicates (basic comparisons, ordering comparisons, string operations, JSON `Data` operations, logical operators) follows the [common structure](#common-structure) above.

### Size Predicates

Because the `size` field on `File` was made nullable to support the two-phase upload flow (see [`finalizeFileUpload`](/graphql-api/mutations/finalize-file-upload.md)), `FileWhereInput` exposes null-check predicates in addition to the usual numeric comparisons:

| Field        | Type      | Description                                                     |
| ------------ | --------- | --------------------------------------------------------------- |
| `size`       | `Int`     | Equal to size                                                   |
| `sizeNEQ`    | `Int`     | Not equal to size                                               |
| `sizeIn`     | `[Int!]`  | Size is in the provided list                                    |
| `sizeNotIn`  | `[Int!]`  | Size is not in the provided list                                |
| `sizeGT`     | `Int`     | Size greater than                                               |
| `sizeGTE`    | `Int`     | Size greater than or equal                                      |
| `sizeLT`     | `Int`     | Size less than                                                  |
| `sizeLTE`    | `Int`     | Size less than or equal                                         |
| `sizeIsNil`  | `Boolean` | Size has not been populated yet (file is awaiting finalization) |
| `sizeNotNil` | `Boolean` | Size has been populated (upload finalized)                      |

### Examples

Find files that have been created but not yet finalized:

```graphql
query PendingUploads {
  files(where: { sizeIsNil: true }) {
    edges {
      node {
        id
        filename
        createdAt
      }
    }
  }
}
```

Find finalized files larger than one megabyte:

```graphql
query LargeFinalizedFiles {
  files(
    where: {
      and: [
        { sizeNotNil: true },
        { sizeGT: 1048576 }
      ]
    }
  ) {
    edges {
      node {
        id
        filename
        size
      }
    }
  }
}
```

## Related Documentation

* [InventoryItemWhereInput](/graphql-api/inputs/inventoryitemwhereinput.md) - Detailed documentation for inventory item filtering
* [GraphQL Queries](/graphql-api/queries.md) - How to use WhereInput in various queries
* [Error Handling](/graphql-api/error-handling.md) - Common errors when using WhereInput types
* [Repository Type](/graphql-api/types/repository.md) - Repository type documentation with parent/children edges
* [`finalizeFileUpload`](/graphql-api/mutations/finalize-file-upload.md) - Mutation that populates `File.size` after upload


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.pyck.cloud/graphql-api/inputs/where-inputs.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
