FQL v4 will be decommissioned on June 30, 2025. Ensure that you complete your migration from FQL v4 to FQL v10 by that date.

For more details, see the v4 EOL announcement and migration guide. Contact support@fauna.com with any questions.

Index terms

When you create an index you have the option of including one or more entries in the terms field. Each entry represents a field name to make searchable in the index’s source collection(s).

Let’s add some documents to a collection named cars:

client.query([
  q.Create(
    q.Ref(q.Collection('cars'), 1),
    { data: { make: 'Honda', model: 'Civic', doors: 4 } }
  ),
  q.Create(
    q.Ref(q.Collection('cars'), 2),
    { data: { make: 'Honda', model: 'Accord', doors: 2 } }
  ),
  q.Create(
    q.Ref(q.Collection('cars'), 3),
    { data: { make: 'Toyota', model: 'Camry', doors: 4 } }
  ),
])
.then((res) => console.log(res))
.catch((err) => console.error(
  'Error: [%s] %s: %s',
  err.name,
  err.message,
  err.errors()[0].description,
))
[
  {
    ref: Ref(Collection("cars"), "1"),
    ts: 1645226205590000,
    data: { make: 'Honda', model: 'Civic', doors: 4 }
  },
  {
    ref: Ref(Collection("cars"), "2"),
    ts: 1645226205590000,
    data: { make: 'Honda', model: 'Accord', doors: 2 }
  },
  {
    ref: Ref(Collection("cars"), "3"),
    ts: 1645226205590000,
    data: { make: 'Toyota', model: 'Camry', doors: 4 }
  }
]
Query metrics:
  •    bytesIn:  396

  •   bytesOut:  553

  • computeOps:    1

  •    readOps:    0

  •   writeOps:    3

  •  readBytes:   42

  • writeBytes:  647

  •  queryTime: 28ms

  •    retries:    0

In order to search values in the make field, we can include make in the terms definition in an index called cars_by_make:

client.query(
  q.CreateIndex(
    {
      name: 'cars_by_make',
      source: q.Collection('cars'),
      terms: [
        { field: ['data', 'make'] },
      ],
    },
  )
)
.then((ret) => console.log(ret))
.catch((err) => console.error(
  'Error: [%s] %s: %s',
  err.name,
  err.message,
  err.errors()[0].description,
))
{
  ref: Index("cars_by_make"),
  ts: 1641940850400000,
  active: true,
  serialized: true,
  name: "cars_by_make",
  source: Collection("cars"),
  terms: [
    {
      field: ["data", "make"]
    }
  ],
  partitions: 1
}
Query metrics:
  •    bytesIn:   129

  •   bytesOut:   292

  • computeOps:     1

  •    readOps:     0

  •   writeOps:     4

  •  readBytes: 1,635

  • writeBytes:   803

  •  queryTime:  32ms

  •    retries:     0

Note that if any new documents are added to the cars collection which do not include a make field, those documents are not represented in the cars_by_make index.

Now we can use the cars_by_make index to search for documents which match on search criteria for the make field:

client.query(
  q.Map(
    q.Paginate(q.Match(q.Index('cars_by_make'), 'Honda')),
    q.Lambda('car', q.Get(q.Var('car')))
  )
)
.then((ret) => console.log(ret))
.catch((err) => console.error(
  'Error: [%s] %s: %s',
  err.name,
  err.message,
  err.errors()[0].description,
))
{
  data: [
    {
      ref: Ref(Collection("cars"), "1"),
      ts: 1645226205590000,
      data: { make: 'Honda', model: 'Civic', doors: 4 }
    },
    {
      ref: Ref(Collection("cars"), "2"),
      ts: 1645226205590000,
      data: { make: 'Honda', model: 'Accord', doors: 2 }
    }
  ]
}
Query metrics:
  •    bytesIn:  130

  •   bytesOut:  382

  • computeOps:    1

  •    readOps:    3

  •   writeOps:    0

  •  readBytes:  265

  • writeBytes:    0

  •  queryTime: 13ms

  •    retries:    0

If you need your application to support searching by multiple fields, you can create an index with multiple fields in the terms definition. The following example creates an index on the make and model fields in the cars collection:

client.query(
  q.CreateIndex(
    {
      name: 'cars_by_make_and_model',
      source: q.Collection('cars'),
      terms: [
        { field: ['data', 'make'] },
        { field: ['data', 'model'] },
      ],
    },
  )
)
.then((ret) => console.log(ret))
.catch((err) => console.error(
  'Error: [%s] %s: %s',
  err.name,
  err.message,
  err.errors()[0].description,
))
{
  ref: Index("cars_by_make_and_model"),
  ts: 1641943522140000,
  active: true,
  serialized: true,
  name: "cars_by_make_and_model",
  source: Collection("cars"),
  terms: [
    { field: ["data", "make"] },
    { field: ["data", "model"] }
  ],
  partitions: 1
}
Query metrics:
  •    bytesIn:   177

  •   bytesOut:   339

  • computeOps:     1

  •    readOps:     0

  •   writeOps:     4

  •  readBytes: 1,697

  • writeBytes:   890

  •  queryTime:  46ms

  •    retries:     0

Queries against an index with multiple terms must include an array of search criteria. The criteria are compared against the fields in the terms field in the order in which they are listed. The following example searches for documents in the cars collection which match Toyota in the make field and Camry in the model field:

client.query(
  q.Map(
    q.Paginate(q.Match(q.Index('cars_by_make_and_model'), ['Toyota', 'Camry'])),
    q.Lambda('car', q.Get(q.Var('car')))
  )
)
.then((ret) => console.log(ret))
.catch((err) => console.error(
  'Error: [%s] %s: %s',
  err.name,
  err.message,
  err.errors()[0].description,
))
{
  data: [
    {
      ref: Ref(Collection("cars"), "3"),
      ts: 1645226205590000,
      data: { make: 'Toyota', model: 'Camry', doors: 4 }
    }
  ]
}
Query metrics:
  •    bytesIn: 151

  •   bytesOut: 203

  • computeOps:   1

  •    readOps:   2

  •   writeOps:   0

  •  readBytes: 151

  • writeBytes:   0

  •  queryTime: 9ms

  •    retries:   0

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!