---
title: Search query syntax
description: >-
  The query syntax Shopify uses for searching and filtering, in GraphQL query
  arguments, REST query parameters, webhook filters, and the admin.
source_url:
  html: 'https://shopify.dev/docs/api/usage/search-syntax'
  md: 'https://shopify.dev/docs/api/usage/search-syntax.md'
---

# Search query syntax

Shopify uses one search query syntax across the platform. The same grammar of terms, connectives, modifiers, and comparators applies wherever you search or filter:

* **GraphQL APIs**: the `query` argument on a connection, for example `products(first: 5, query: "created_at:>'2020-10-21'")`. Supported by the [GraphQL Admin API](https://shopify.dev/docs/api/admin-graphql), the [Storefront API](https://shopify.dev/docs/api/storefront), and the [Customer Account API](https://shopify.dev/docs/api/customer).
* **REST Admin API**: the `query` parameter on search endpoints, written `query=first_name:Bob`.
* **Webhook subscriptions**: [delivery filters](https://shopify.dev/docs/apps/build/webhooks/delivery-filtering) use the same grammar to decide whether an event is delivered.
* **The Shopify admin, mobile apps, and customer segments**: the search fields merchants use directly.

This page defines the grammar. Which fields you can query is defined per resource in each API's reference documentation.

The grammar tables below write their examples in the parameter form, `query=title:red`. In a GraphQL request the same string is the value of the `query` argument, `query: "title:red"`.

***

## Search query grammar overview

A string query is a text search made up of terms, connectives, modifiers, and comparators. The search grammar rules defined here can be built into larger structures as defined by the [search query syntax](#search-query-syntax).

The search grammar is expressed similarly to [EBNF](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form) and uses the following baseline terminal symbols:

| Item | Description |
| - | - |
| `whitespace` | Any sequence of space, tab, or newline characters. |
| `name` | Any sequence of non-whitespace, non-special characters. For more information, refer to [Special characters](#special-characters). |
| `value` | Any name, or any quoted string (single or double quotes are both permitted). Date values must be a string surrounded by quotes. |

### Query

```text
Query = Term { [ whitespace Connective ] whitespace Term }
```

A query is one or more terms separated by whitespace and optionally by single connectives. A query may have optional leading and trailing whitespace.

`query=John Smith`

### Connectives

```text
Connective = "AND" | "OR"
```

When a connective is not specified between two terms, `AND` is implied.

`query=state:enabled OR state:disabled`

### Terms

```text
Term = [ Modifier ] ( "(" Query ")" | [ name Comparator ] value )
```

A term consists of an optional modifier, followed either by a subquery (enclosed in parentheses) or a value with an optional name-and-comparator.

`query=-first_name:Bob AND orders_count:>3 orders_count:<=4`

### Modifiers

```text
Modifier = "-" | "NOT" whitespace
```

Supported modifiers are `-` with no following whitespace, or `NOT` followed by whitespace. Both mean the same thing.

`query=-first_name:Bob`

`query=NOT first_name:Bob`

Modifiers apply only to the terms that immediately follow them. You can use a modifier on any term, including a subquery. You can also use multiple modifiers in one query.

`query=state:enabled NOT first_name:Bob`

`query=NOT first_name:Bob NOT first_name:Norman`

`query=state:enabled NOT (first_name:Bob OR first_name:Norman)`

### Comparators

```text
Comparator = ":" | ":<" | ":>" | ":<=" | ":>="
```

The following comparators are supported for search queries:

* `:`: equality

* `:<`: less-than

* `:>`: greater-than

* `:<=`: less-than-or-equal-to

* `:>=`: greater-than-or-equal-to

  **Note:**

  Equality (`:`) depends on how a field is indexed.

  * For numeric fields, `:` represents equality.
  * For tokenized fields, equality exists if the term is found anywhere in the field.
  * For non-tokenized fields, the search query string must match the searched field exactly.

### Special characters

Special characters serve specific functions in search query syntax and need to be escaped with a backslash. For example, `: \ ( )`.

Names can include the characters `-`, `'`, and `"` but can't start with them. Names can include escaped characters using backslash escaping.

***

## Search query syntax

Shopify search query syntax is based on the defined grammar and enables the following search behavior. The following table describes the different types of search queries and their syntax:

| Type | Description | Example syntax | Example explained |
| - | - | - | - |
| Field search | A search that applies to terms in specific fields. If you specify an invalid field, then the query is ignored and all results are returned. | `query=first_name:Bob age:27` | A search for "Bob" in the `first_name` field AND "27" in the `age` field. The value must immediately follow the field with no whitespace. `first_name: Bob` searches for the terms "first\_name" and "Bob". |
| Default search | A case-insensitive search of all the fields in a document. | * `query=Bob Norman`
* `query=title:Bob Norman` | A case-insensitive search for both "bob" AND "norman" anywhere in the document. When combined with field search, this becomes "title:bob" AND "norman" anywhere in the document. To send composite terms to a field, wrap them in quotes or give them each a field prefix. |
| Range search | A search that specifies a range of values to search against. Supported operators: `>`, `>=`, `<` and `<=`. | `query=orders_count:>16 orders_count:<=30` | A search that matches documents where the `orders_count` field is greater than 16 and less than or equal to 30. Equality (`:`) is specified by `orders_count:16`, not `orders_count:=16`. `orders_count:=16` searches for the term "=16" in the `orders_count` field. Refer to the [range query example](#using-created_at-in-a-range-query) for a performance consideration with range searches. |
| NOT query | A search that excludes documents that include the specified value. The NOT operator must be capitalized to execute a NOT query, and only applies to the specified space-separated term or query. `-` must precede the field, value, or subquery. For example, `-field:value -value -(subquery)`. | - `query=-bob`
- `query=NOT bob` | Searches that exclude documents that include the term "bob". |
| Boolean operators | A search that allow terms to be combined through logic operators. | * `query=bob OR norman AND Shopify`
* `query=bob OR norman Shopify` | - `query=bob OR norman AND Shopify`: Searches for documents that must have the term "Shopify" and have at least one of the terms "bob" or "norman".
- `query=bob OR norman Shopify`: Equivalent to the query above, since OR has a higher operator precedence than AND.An explicit AND operator isn't needed between "bob OR norman" and "Shopify" because the AND is the default boolean operator between terms or queries. |
| Grouping | A search using parentheses to group clauses to form subqueries. | `query=state:disabled AND ("sale shopper" OR VIP)` | A search for disabled customers with "sale shopper" or "VIP" tags. |
| Phrase query | A search for a group of words surrounded by double quotes. | `query=first_name:"Bob Norman"` | A search for the term "bob" followed immediately by the term "norman" in the `first_name` field. Phrase queries can be used without the `query` field. For example, `"Bob Norman"`. |
| Prefix query | A search that matches documents containing terms that begin with a specified set of characters. Shopify supports `*` for wildcard matching. | `query=norm*` | A search for all the terms that begin with the prefix "norm", such as "norman". |
| Exists query | A search that matches documents with a non-null value in the specified field. Shopify supports `*` for wildcard matching. | `query=published_at:*` | A search for non-null values in the `published_at` field. The query can be combined with a NOT query to find fields missing a value. For example, `-published_at:*`. |

**Note:**

In storefront search (the Storefront API `search` query and the online store search page), a phrase query without a field name matches only product titles and descriptions. To match an exact phrase in another field, add the field name, for example `tag:"summer sale"` or `vendor:"Blue Harbor"`. Field-scoped phrase queries are recommended whenever you know which field contains the phrase.

### Examples

The following examples send the query string as the `query` argument in a GraphQL request. The same strings work as a `query=` parameter on REST Admin API search endpoints, as a webhook delivery filter, and in the admin's search fields.

**Note:**

The examples below use function arguments that don't exist for your store. You need to edit the function arguments used in the examples below.

#### Using `created_at` in a range query

List 5 products that were added to a store after October 21st, 2020.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

```graphql
{
  products(first: 5, query: "created_at:>'2020-10-21T23:39:20Z'" ) {
    edges {
      node {
        id
        title
        createdAt
      }
    }
  }
}
```

**Tip:**

Searching for resources using a range query might be slow or timeout if the collection of resources is sufficiently large, and the search field is different from the specified (or default) sort key. If your query is slow or returns an error, then try specifying a sort key that matches the field used in the search. For example, `query: "created_at:>2020-10-21", sortKey: CREATED_AT`.

#### Using `title`

List 5 products with the name "Caramel Apple".

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

```graphql
{
  products(first: 5, query: "title:Caramel Apple") {
    edges {
      node {
        id
        title
        createdAt
      }
    }
  }
}
```

**Note:**

`query: "title:Caramel Apple"` is equivalent to `query: "title: \"Caramel Apple\""` (phrase query).

List 10 products that include terms that begin with the prefix `head`, such as `headphones`.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

```graphql
{
  shop {
    id
    name
  }
  products(first: 10, query:"title:head*") {
    edges {
      node {
        productType
        title
      }
    }
  }
}
```

#### Using `OR` and a range

List 5 products with the name "Caramel Apple", or products that have an inventory of over 500 items and less than or equal to 1000 items.

## POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json

```graphql
{
  products(first: 5, query: "(title:Caramel Apple) OR (inventory_total:>500 inventory_total:<=1000)" ) {
    edges {
      node {
        id
        title
        createdAt
        totalInventory
      }
    }
  }
}
```

***

## Syntax debugging

The GraphQL Admin API provides tools for search syntax validation and debugging. Requests with malformed queries return warnings in the `extensions` section of the response. This feedback explains how the query was parsed and any incompatibilities encountered:

```json
{
"data": {
  "products": {
    "nodes": []
  }
},
"extensions": {
  "search": [{
    "path": ["products"],
    "query": "name:blue jeans",
    "parsed": {
      "and": [
        { "field": "default", "match_all": "jeans" },
        { "field": "name", "match_all": "blue" }
      ]
    },
    "warnings": [{
      "field": "name",
      "message": "Invalid search field for this query."
    }]
  }]
}
}
```

**Note:**

To receive the search extension for all queries with and without warnings, you can send a `Shopify-Search-Query-Debug=1` header to enable it manually.

***
