# group\_by\_exp

Groups an array using a Liquid expression to determine the group key. Unlike `group_by`, which groups by a direct property value, `group_by_exp` lets you write arbitrary expressions to compute the grouping key.

```liquid
{% assign by_price_range = products | group_by_exp: "product", "product.price > 100" %}
{% for group in by_price_range %}
  {% log group.name | append: ": " | append: group.items.size | append: " products" %}
{% endfor %}
```

#### Syntax

```liquid
{{ array | group_by_exp: item_name, expression }}
```

| Parameter    | Description                                              |
| ------------ | -------------------------------------------------------- |
| `array`      | Array of objects to group                                |
| `item_name`  | Variable name for the current item inside the expression |
| `expression` | Liquid expression that produces the group key            |

#### Return Value

Returns an array of group objects:

| Property | Type  | Description                                              |
| -------- | ----- | -------------------------------------------------------- |
| `name`   | any   | The computed key value shared by all items in this group |
| `items`  | Array | Array of items that produced this key value              |

#### Examples

**Group products by price range:**

```liquid
{% assign by_range = products | group_by_exp: "p", "p.price > 50" %}
{% for group in by_range %}
  {% if group.name == true %}
    {% log "Premium products: " | append: group.items.size %}
  {% else %}
    {% log "Budget products: " | append: group.items.size %}
  {% endif %}
{% endfor %}
```

**Group by first letter of title:**

```liquid
{% assign by_letter = products | group_by_exp: "p", "p.title | slice: 0" %}
{% for group in by_letter %}
  {% log group.name | append: ": " | append: group.items.size | append: " products" %}
{% endfor %}
```

**Group orders by fulfillment state:**

```liquid
{% assign by_state = orders | group_by_exp: "o", "o.fulfillment_status | default: 'unfulfilled'" %}
{% for group in by_state %}
  {% log group.name | append: ": " | append: group.items.size %}
{% endfor %}
```

**Group by computed value using filters:**

```liquid
{% assign by_month = orders | group_by_exp: "o", "o.created_at | date: '%Y-%m'" %}
{% for group in by_month %}
  {% log group.name | append: ": " | append: group.items.size | append: " orders" %}
{% endfor %}
```

Output:

```
2025-01: 156 orders
2025-02: 203 orders
2025-03: 178 orders
```

**Group line items by quantity tier:**

```liquid
{% assign by_tier = line_items | group_by_exp: "item", "item.quantity > 10" %}
{% for group in by_tier %}
  {% if group.name == true %}
    {% log "Bulk orders: " | append: group.items.size %}
  {% else %}
    {% log "Regular orders: " | append: group.items.size %}
  {% endif %}
{% endfor %}
```

#### Notes

* The `item_name` parameter defines how you reference each item inside the expression
* The expression can use any Liquid filters and operators
* The expression result becomes the group `name` — it can be a string, number, boolean, etc.
* Groups are returned in the order their keys are first encountered
* For simple property-based grouping, `group_by` is more concise
* See also: `group_by`, `group_by_property`, `group_by_fast`


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.datajet-app.com/liquid/filters/group_by_exp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
