---
title: Indexing JSON
description: Add JSON and JSONB types to the index
canonical: https://docs.paradedb.com/documentation/indexing/indexing-json
---
When indexing JSON, ParadeDB automatically indexes all sub-fields of the JSON object. The type of each sub-field is also inferred automatically.
For example, consider the following statement where `metadata` is `JSONB`:
```sql SQL
CREATE INDEX search_idx ON mock_items
USING bm25 (id, metadata)
WITH (key_field='id');
```
```ts Drizzle
import { indexing } from "@paradedb/drizzle-paradedb";
indexing.bm25Index("search_idx").on(mockItems.id, mockItems.metadata);
```
```python Django
from django.db import connection
from paradedb.indexes import BM25Index
with connection.schema_editor() as schema_editor:
schema_editor.add_index(
MockItem,
BM25Index(
fields={
"id": {},
"metadata": {},
},
key_field="id",
name="search_idx",
),
)
```
```python SQLAlchemy
from sqlalchemy import Index
from paradedb.sqlalchemy import indexing
idx = Index(
"search_idx",
indexing.BM25Field(MockItem.id),
indexing.BM25Field(MockItem.metadata_),
postgresql_using="bm25",
postgresql_with={"key_field": "id"},
)
with engine.begin() as conn:
idx.create(conn)
```
```ruby Rails
ActiveRecord::Base.connection.add_bm25_index(
:mock_items,
fields: {
id: {},
metadata: {}
},
key_field: :id,
name: :search_idx
)
```
```cs EF Core
modelBuilder.Entity()
.HasBm25Index("search_idx", e => e.Id)
.HasField(e => e.Metadata);
```
A single `metadata` JSON may look like:
```json
{ "color": "Silver", "location": "United States" }
```
ParadeDB will automatically index both `metadata.color` and `metadata.location` as text.
By default, all text sub-fields of a JSON object use the same tokenizer. The tokenizer can be configured the same way as text fields:
```sql SQL
CREATE INDEX search_idx ON mock_items
USING bm25 (id, (metadata::pdb.ngram(2,3)))
WITH (key_field='id');
```
```ts Drizzle
import { indexing, tokenizer } from "@paradedb/drizzle-paradedb";
indexing
.bm25Index("search_idx")
.on(
mockItems.id,
indexing.bm25Field(mockItems.metadata, tokenizer.ngram(2, 3)),
);
```
```python Django
from django.db import connection
from paradedb.indexes import BM25Index
from paradedb.search import Tokenizer
with connection.schema_editor() as schema_editor:
schema_editor.add_index(
MockItem,
BM25Index(
fields={
"id": {},
"metadata": {
"tokenizer": Tokenizer.ngram(2, 3),
},
},
key_field="id",
name="search_idx",
),
)
```
```python SQLAlchemy
from sqlalchemy import Index
from paradedb.sqlalchemy import indexing, tokenizer
idx = Index(
"search_idx",
indexing.BM25Field(MockItem.id),
indexing.BM25Field(
MockItem.metadata_,
tokenizer=tokenizer.ngram(2, 3),
),
postgresql_using="bm25",
postgresql_with={"key_field": "id"},
)
with engine.begin() as conn:
idx.create(conn)
```
```ruby Rails
ActiveRecord::Base.connection.add_bm25_index(
:mock_items,
fields: {
id: {},
metadata: { tokenizer: Tokenizer.ngram(2, 3) }
},
key_field: :id,
name: :search_idx
)
```
```cs EF Core
modelBuilder.Entity()
.HasBm25Index("search_idx", e => e.Id)
.HasField(e => e.Metadata, Tokenizer.Ngram(2, 3));
```
Instead of indexing the entire JSON, sub-fields of the JSON can be indexed individually. This allows for configuring separate tokenizers
within a larger JSON:
```sql SQL
CREATE INDEX search_idx ON mock_items
USING bm25 (id, ((metadata->>'color')::pdb.ngram(2,3)))
WITH (key_field='id');
```
```ts Drizzle
import { indexing, tokenizer } from "@paradedb/drizzle-paradedb";
indexing
.bm25Index("search_idx")
.on(
mockItems.id,
indexing.bm25Field(
indexing.jsonText(mockItems.metadata, "color"),
tokenizer.ngram(2, 3),
),
);
```
```python Django
from django.db import connection
from paradedb.indexes import BM25Index
from paradedb.search import Tokenizer
with connection.schema_editor() as schema_editor:
schema_editor.add_index(
MockItem,
BM25Index(
fields={
"id": {},
"metadata": {
"json_keys": {
"color": {
"tokenizer": Tokenizer.ngram(2, 3),
},
},
},
},
key_field="id",
name="search_idx",
),
)
```
```python SQLAlchemy
from sqlalchemy import Index
from paradedb.sqlalchemy import expr, indexing, tokenizer
idx = Index(
"search_idx",
indexing.BM25Field(MockItem.id),
indexing.BM25Field(
expr.json_text(MockItem.metadata_, "color"),
tokenizer=tokenizer.ngram(2, 3),
),
postgresql_using="bm25",
postgresql_with={"key_field": "id"},
)
with engine.begin() as conn:
idx.create(conn)
```
```ruby Rails
ActiveRecord::Base.connection.add_bm25_index(
:mock_items,
fields: {
id: {},
"metadata->>'color'" => { tokenizer: Tokenizer.ngram(2, 3) }
},
key_field: :id,
name: :search_idx
)
```
```cs EF Core
modelBuilder.Entity()
.HasBm25Index("search_idx", e => e.Id)
.HasField("metadata->>'color'", Tokenizer.Ngram(2, 3));
```