# JSONB

Clear offers JSONB functions through `Clear::SQL::JSONB` helper and the Expression Engine.

JSONB is a great No-SQL mapping under PostgreSQL. It helps you to store value and documents which otherwise would be difficult

Let's imaging a table `events` where you store the events of differents suppliers:

## Postgres limitation and Clear's answer

The main limitation of JSONB is the "simple" syntax is not indexable. For example:

```sql
  SELECT * FROM events WHERE payload->'source'->>'name' = 'Asana'
```

The code above will not use any indexes and will do a sequencial scan over your table.

However, using the `@>` operator and a `gin` index on your column will improve drastically the performances:

```sql
  SELECT * FROM events WHERE payload @> '{"source": {"name": "Asana"}}'
```

Obviously, the second syntax is more complex and error prone. Clear offers leverage and simplicity:

```ruby
  Event.query.where{ payload.jsonb("source.name") == "asana" }
  #  SELECT * FROM events WHERE payload @> '{"source": {"name": "Asana"}}'
```

## Expression Engine

### jsonb

calling `node.jsonb(key)` on expression node will resolve to:

* node->'key\_elm1'->'key\_elm...n'

Using equality testing between a jsonb path and a literal will use the indexable notation `@>` :

```ruby
where{ data.jsonb('a.b.c') == 1 }
#output:
# data @> '{"a":{"b":{"c":1}}}'
```

In the case the operation is not indexable (e.g. the value is variable, operator is not equality...), Clear will automatically switch back to the arrow `->` notation:

```ruby
where{ data.jsonb('a.b.c') == raw("NOW()") }
# output:
# data->'a'->'b'->'c' = NOW()
```

**Casting**

You can cast the element using `cast` after your expression:

```ruby
where{ data.jsonb("a.b").cast("text") == "o" }
# output:
# data->'a'->'b'::text == 'o'
```

Note: If you cast the `jsonb`, clear will never use `@>` operator

### From path to arrow notation

```ruby
Clear::SQL::JSONB.jsonb_resolve("data", "a.b.c", "text")
# output:
# data->'a'->'b'->'c'::text
```

## Use outside Expression Engine (`@>` operator)

```ruby
Clear::SQL::JSONB.jsonb_eq(data, "a.b.c", "value")
#output:
# data @> {"a":{"b":{"c":"value"}}}
```
