Indexes

Indexes allow for the organization and retrieval of documents by attributes other than their References. They are defined as documents within the system indexes collection.

A Set is a sorted group of immutable data from a collection. An Index is a group of sets within a collection. An index is also a database entity that facilitates efficient data lookups.

This section covers the following topics:

Example index

The simplest index is called a "collection" index; it has no terms or values defined. This means that the index includes all documents with no search terms, and that the index returns the references to each indexed document. Such an index can be created with just a name and a source collection:

client.Query(
  CreateIndex(
    Obj("name", "new-index", "source", Collection("spells"))));
{
  "ref": { "@ref": "indexes/new-index" },
  "class": { "@ref": "indexes" },
  "ts": 1509244540009619,
  "active": false,
  "partitions": 8,
  "name": "new-index",
  "source": { "@ref": "classes/spells" }
}
curl https://db.fauna.com/ \
    -u fnAChGwBcAACAO70ziE0cfROosNJHdgBmJU1PgpL: \
    -d '{
          "create_index": {
            "object": { "name": "new-index", "source": { "collection": "spells" } }
          }
        }'
HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "indexes/new-index" },
    "class": { "@ref": "indexes" },
    "ts": 1509244540009619,
    "active": false,
    "partitions": 8,
    "name": "new-index",
    "source": { "@ref": "classes/spells" }
  }
}
result, _ := client.Query(
    f.CreateIndex(
        f.Obj{"name": "new-index", "source": f.Collection("spells")},
    ),
)

fmt.Println(result)
map[ref:{new-index 0xc4201ef8e0 <nil>} ts:1509244540009619 active:false partitions:8 name:new-index source:{spells 0xc4201efb40 <nil>}]
System.out.println(
      client.query(
          CreateIndex(
              Obj(
                  "name", Value("new-index"),
                  "source", Collection(Value("spells"))
              )
          )
      ).get());
{
  ref: ref(id = "new-index", collection = ref(id = "indexes")),
  ts: 1526674566835735,
  active: false,
  partitions: 8,
  name: "new-index",
  source: ref(id = "spells", collection = ref(id = "collections"))
}
client.query(
  q.CreateIndex({
    name: 'new-index',
    source: q.Collection('spells'),
  })
)
.then((ret) => console.log(ret))
{ ref: Ref(id=new-index, collection=Ref(id=indexes)),
  ts: 1527275052756370,
  active: false,
  partitions: 8,
  name: 'new-index',
  source: Ref(id=spells, collection=Ref(id=collections)) }
client.query(
  q.create_index(
    {"name": "new-index", "source": q.collection("spells")}
  ))
{
  "ref": { "@ref": "indexes/new-index" },
  "class": { "@ref": "indexes" },
  "ts": 1509244540009619,
  "active": false,
  "partitions": 8,
  "name": "new-index",
  "source": { "@ref": "classes/spells" }
}
client.query(
  CreateIndex(
    Obj("name" -> "new-index", "source" -> Collection("spells"))))
{
  "ref": { "@ref": "indexes/new-index" },
  "class": { "@ref": "indexes" },
  "ts": 1509244540009619,
  "active": false,
  "partitions": 8,
  "name": "new-index",
  "source": { "@ref": "classes/spells" }
}

Index fields

Field Name Field Type Definition and Requirements

name

The logical name of the index. Cannot be events, sets, self, documents, or _.

source

A Collection reference, or an array of one or more source objects describing source collections and (optional) binding fields.

terms

Optional - An array of Term objects describing the fields that should be searchable. Indexed terms can be used to search for field values, via the Match function. The default is an empty Array.

values

Optional - An array of Value objects describing the fields that should be reported in search results. The default is an empty Array. When no values fields are defined, search results report the indexed document’s Reference.

unique

Optional - If true, maintains a unique constraint on combined terms and values. The default is false.

serialized

Optional - If true, writes to this index are serialized with concurrent reads and writes. The default is true.

permissions

Optional - Indicates who is allowed to read the index. The default is everyone can read the index.

data

Optional - This is user-defined metadata for the index. It is provided for the developer to store information at the index level. The default is an empty object having no data.

The length of the field values specified for the terms or values fields must not exceed 32k bytes. The maximum size of an index entry, which is comprised of the terms and values content (and some overhead to distinguish multiple fields), must not exceed 64k bytes. If an index entry is too large, the query that created/updated the index entry fails.

Source objects

Source objects describe the source collection of index entries and, optionally, bindings. A binding must be a pure Lambda function that emits values to be used as a term and/or value.

An index cannot be created in the same transaction that creates its source collection(s).

The collection field can be a single collection reference or set of references. Documents within collections matching the collection field apply the associated bindings to be used in the index’s terms or values. A collection reference can only exist in one source object. If the collection field is a wildcard (_), the index evaluates all collections. Bindings associated with a wildcard are only used if the collection is not matched by any other source object.

Field Type Definition and Requirements

collection

Ref

The collection or collections to be indexed, or a wildcard (_).

fields

Object

An object mapping a binding’s name to a Lambda function.

The following examples demonstrates the structure of a source object, which includes an example binding object:

Value result = await client.Query(
  Obj(
    "source", Obj(
      "collection", Collection("collection"),
      "fields", Obj(
        "binding1", Query(
          Lambda(
            "document",
            Select(Arr("data", "field"), Var("document"))
          )
        )
      )
    )
  )
);

IResult<Value> data = result.To<Value>();
data.Match(
  Success: value => Console.WriteLine($"{value}"),
  Failure: error => Console.WriteLine($"Query failed:\n{error}")
);
ObjectV(source: ObjectV(collection: RefV(id = "collection", collection = RefV(id = "collections")),fields: ObjectV(binding1: QueryV(System.Collections.Generic.Dictionary`2[System.String,FaunaDB.Query.Expr]))))
result, err := client.Query(
  f.Obj{
    "source": f.Obj{
      "collection": f.Collection("collection"),
      "fields": f.Obj{
        "binding1": f.Query(
          f.Lambda(
            "document",
            f.Select(f.Arr{"data", "field"}, f.Var("document"))))}}})

if (err != nil) {
  fmt.Println(err)
} else {
  fmt.Println(result)
}
map[source:map[collection:{collection 0xc00017ef60 0xc00017ef60 <nil>} fields:map[binding1:{[123 34 108 97 109 98 100 97 34 58 34 100 111 99 117 109 101 110 116 34 44 34 101 120 112 114 34 58 123 34 115 101 108 101 99 116 34 58 91 34 100 97 116 97 34 44 34 102 105 101 108 100 34 93 44 34 102 114 111 109 34 58 123 34 118 97 114 34 58 34 100 111 99 117 109 101 110 116 34 125 125 125]}]]]
System.out.println(
    client.query(
        Obj(
            "source", Obj(
                "collection", Collection("collection"),
                "fields", Obj(
                    "binding1", Query(
                        Lambda(
                            "document",
                            Select(
                                Arr(Value("data"), Value("field")),
                                Var("document")
                            )
                        )
                    )
                )
            )
        )
    ).get());
{source: {collection: ref(id = "collection", collection = ref(id = "collections")), fields: {binding1: QueryV({lambda=document, expr={select=[data, field], from={var=document}}})}}}
client.query({
  source: {
    collection: q.Collection('collection'),
    fields: {
      binding1: q.Query(
        q.Lambda(
          'document',
          q.Select(['data', 'field'], q.Var('document'))
        )
      ),
    },
  },
})
.then((ret) => console.log(ret))
{ source:
   { collection: Collection("collection"),
     fields:
      { binding1:
         Query(Lambda("document", Select(["data", "field"], Var("document")))) } } }
print(client.query({
  "source": {
    "collection": q.collection("collection"),
    "fields": {
      "binding1": q.query(
        q.lambda_(
          "document",
          q.select(["data", "field"], q.var("document"))
        )
      )
    }
  }
}))
{'source': {'collection': Ref(id=collection, collection=Ref(id=collections)), 'fields': {'binding1': Query({'lambda': 'document', 'expr': {'select': ['data', 'field'], 'from': {'var': 'document'}}})}}}
Not available in this language yet.
println(Await.result(
  client.query(
    Obj(
      "source" -> Obj(
        "collection" -> Collection("collection"),
        "fields" -> Obj(
          "binding1" -> Query(
            Lambda(
              "document",
              Select(Arr("data", "field"), Var("document"))
            )
          )
        )
      )
    )
  ),
  5.seconds
))
{source: {collection: ref(id = "collection", collection = ref(id = "collections")), fields: {binding1: {lambda: "document", expr: {select: ["data", "field"], from: {var: "document"}}}}}}
Not available in this language yet.

Binding objects

A binding object contains field names bound to pure, single-argument Lambda functions. The function must take the document to be indexed and emit either a single scalar value or an array of scalar values. Binding functions are not permitted to perform reads or writes.

Functions that cannot be used in bindings include:

Functions that cannot be used in bindings when they operate on sets or pages include:

Value result = await client.Query(
  Obj(
    "binding1", Query(
      Lambda(
        "document",
        Select(Arr("data", "field"), Var("document"))
      )
    )
  )
);

IResult<Value> data = result.To<Value>();
data.Match(
  Success: value => Console.WriteLine($"{value}"),
  Failure: error => Console.WriteLine($"Query failed:\n{error}")
);
ObjectV(binding1: QueryV(System.Collections.Generic.Dictionary`2[System.String,FaunaDB.Query.Expr]))
curl https://db.fauna.com/ \
    -u fnACrVIrDDACAFiX3FN4PhwADpl7dtPRhWObP08j: \
    -d '{
          "object": {
            "binding1": {
              "query": {
                "lambda": "document",
                "expr": {
                  "select": [ "data", "field" ],
                  "from": { "var": "document" }
                }
              }
            }
          }
        }'
HTTP/1.1 200 OK
{
  "resource": {
    "binding1": {
      "@query": {
        "lambda": "document",
        "expr": {
          "select": [ "data", "field" ],
          "from": { "var": "document" }
        }
      }
    }
  }
}
result, err := client.Query(
  f.Obj{
    "binding1": f.Query(
      f.Lambda(
        "document",
        f.Select(f.Arr{"data", "field"}, f.Var("document"))))})

if (err != nil) {
  fmt.Println(err)
} else {
  fmt.Println(result)
}
map[binding1:{[123 34 108 97 109 98 100 97 34 58 34 100 111 99 117 109 101 110 116 34 44 34 101 120 112 114 34 58 123 34 115 101 108 101 99 116 34 58 91 34 100 97 116 97 34 44 34 102 105 101 108 100 34 93 44 34 102 114 111 109 34 58 123 34 118 97 114 34 58 34 100 111 99 117 109 101 110 116 34 125 125 125]}]
System.out.println(
    client.query(
        Obj(
            "binding1", Query(
                Lambda(
                    "document",
                    Select(
                        Arr(Value("data"), Value("field")),
                        Var("document")
                    )
                )
            )
        )
    ).get());
{binding1: QueryV({lambda=document, expr={select=[data, field], from={var=document}}})}
client.query({
  binding1: q.Query(
    q.Lambda('document', q.Select(['data', 'field'], q.Var('document')))
  ),
})
.then((ret) => console.log(ret))
{ binding1:
   Query(Lambda("document", Select(["data", "field"], Var("document")))) }
print(client.query({
  "binding1": q.query(
    q.lambda_( "document", q.select(["data", "field"], q.var("document")))
  )
}))
{'binding1': Query({'lambda': 'document', 'expr': {'select': ['data', 'field'], 'from': {'var': 'document'}}})}
$client.query do
  {
    binding1: query(do |document| select(['data', 'field'], document) end)
  }
end
{
  "binding1": {
    "@query": {
      "lambda": "document",
      "expr": {
        "select": [ "data", "field" ],
        "from": { "var": "document" }
      }
    }
  }
}
println(Await.result(
  client.query(
    Obj(
      "binding1" -> Query(
        Lambda(
          "document",
          Select(Arr("data", "field"), Var("document"))
        )
      )
    )
  ),
  5.seconds
))
{binding1: {lambda: "document", expr: {select: ["data", "field"], from: {var: "document"}}}}
client.query(
    Obj(
        "binding1" => Query(
            { document in
                Select(path: "data", "field", from: document)
            }
        )
    )
)
{
  "binding1": {
    "@query": {
      "lambda": "document",
      "expr": {
        "select": [ "data", "field" ],
        "from": { "var": "document" }
      }
    }
  }
}

Term objects

Term objects describe the fields whose values are used to search for entries in the index.

When a term field is missing from an indexed document, the field’s value in the index is null.

If no term objects are defined, passing term values to Match is not required. The resulting set contains all documents within the source collection.

A value can be from a field in the document or a binding defined by the source object.

Field Type Definition

field

Array

The path of the field within an document to be indexed.

binding

String

The name of a binding from a source object.

The following example demonstrates an index’s terms field definition with two term objects, the first specifies a binding, the second specifies a document field:

Value result = await client.Query(
  Obj(
    "terms", Arr(
      Obj("binding", "binding1" ),
      Obj("field", Arr("data", "field"))
    )
  )
);

IResult<Value> data = result.To<Value>();
data.Match(
  Success: value => Console.WriteLine($"{value}"),
  Failure: error => Console.WriteLine($"Query failed:\n{error}")
);
ObjectV(terms: Arr(ObjectV(binding: StringV(binding1)), ObjectV(field: Arr(StringV(data), StringV(field)))))
result, err := client.Query(
  f.Obj{
    "terms": f.Arr{
      f.Obj{"binding": "binding1"},
      f.Obj{"field": f.Arr{"data", "field"}} } })

if (err != nil) {
  fmt.Println(err)
} else {
  fmt.Println(result)
}
map[terms:[map[binding:binding1] map[field:[data field]]]]
System.out.println(
    client.query(
        Obj(
            "terms", Arr(
                Obj("binding", Value("binding1")),
                Obj("field", Arr(Value("data"), Value("field")))
            )
        )
    ).get());
{terms: [{binding: "binding1"}, {field: ["data", "field"]}]}
client.query({
  terms: [
    { binding: 'binding1' },
    { field: ['data', 'field'] },
  ],
})
.then((ret) => console.log(ret))
{ terms: [ { binding: 'binding1' }, { field: [Array] } ] }
print(client.query({
  "terms": [
    { "binding": "binding1" },
    { "field": ["data", "field"] }
  ]
}))
{'terms': [{'binding': 'binding1'}, {'field': ['data', 'field']}]}
Not available in this language yet.
println(Await.result(
  client.query(
    Obj(
      "terms" -> Arr(
        Obj("binding" -> "binding1"),
        Obj("field" -> Arr("data", "field"))
      )
    )
  ),
  5.seconds
))
{terms: [{binding: "binding1"}, {field: ["data", "field"]}]}
Not available in this language yet.

Value objects

Value objects describe the fields whose values should be used to sort the index, and whose values should be reported in query results. By default, indexes have no values defined, and return the references of indexed documents.

A value can be from a field in the document, or a binding function defined in a Source objects.

Field Type Definition

field

Array

The path of the field within an document to be indexed.

binding

String

The name of a binding from a Source objects.

reverse

Boolean

Whether this field’s value should sort reversed. Defaults to false.

The document’s reference also appears in before and after cursors when paging through an index with the Paginate function, even if the reference is not included as a values field. Pagination always uses the indexed document’s reference to stabilize pagination.

Any of a document’s fields may be indexed. The value of field in a Term or Value object indicates the position within a document for a field. For example, the field ref refers to the top-level ref field. The field ["data", "address", "street"] refers to the street field contained in an address object within the document’s data object.

The following example demonstrates an index’s values field definition with two term objects, the first specifies a binding, the second specifies a document field that should be sorted in reverse:

Value result = await client.Query(
  Obj(
    "values", Arr(
      Obj("binding", "binding1" ),
      Obj("field", Arr("data", "field"), "reverse", true)
    )
  )
);

IResult<Value> data = result.To<Value>();
data.Match(
  Success: value => Console.WriteLine($"{value}"),
  Failure: error => Console.WriteLine($"Query failed:\n{error}")
);
ObjectV(values: Arr(ObjectV(binding: StringV(binding1)), ObjectV(field: Arr(StringV(data), StringV(field)),reverse: BooleanV(True))))
result, err := client.Query(
  f.Obj{
    "values": f.Arr{
      f.Obj{"binding": "binding1"},
      f.Obj{"field": f.Arr{"data", "field"}, "reverse": true} } })

if (err != nil) {
  fmt.Println(err)
} else {
  fmt.Println(result)
}
map[values:[map[binding:binding1] map[field:[data field] reverse:true]]]
System.out.println(
    client.query(
        Obj(
            "values", Arr(
                Obj("binding", Value("binding1") ),
                Obj(
                    "field", Arr(Value("data"), Value("field")),
                    "reverse", Value(true)
                )
            )
        )
    ).get());
{values: [{binding: "binding1"}, {field: ["data", "field"], reverse: true}]}
client.query({
  values: [
    { binding: 'binding1' },
    { field: ['data', 'field'], reverse: true },
  ],
})
.then((ret) => console.log(ret))
{ values:
   [ { binding: 'binding1' }, { field: [Array], reverse: true } ] }
print(client.query({
  "values": [
    {"binding": "binding1"},
    {"field": ["data", "field"], "reverse": True}
  ]
}))
{'values': [{'binding': 'binding1'}, {'field': ['data', 'field'], 'reverse': True}]}
Not available in this language yet.
println(Await.result(
  client.query(
    Obj(
      "values" -> Arr(
        Obj("binding" -> "binding1"),
        Obj(
          "field" -> Arr("data", "field"),
          "reverse" -> true
        )
      )
    )
  ),
  5.seconds
))
{values: [{binding: "binding1"}, {field: ["data", "field"], reverse: true}]}
Not available in this language yet.

Creating indexes

When an index is added, it is immediately available for reads, but returns incomplete results until it is built. Fauna builds the index asynchronously by scanning over relevant documents. Upon completion, the index’s active field is set to true.

An index cannot be created and read in the same transaction.

When an index is created, documents are immediately indexed if the associated collection contains up to 128 events (which include document creation, updates, and deletion). When an index contains all of a collection’s documents, including each document’s events, it is an "active" index.

For collections with more than 128 events, or those that use a wildcard in their source definition, indexing is handled by a background task, and you may have to wait a short period before the index returns values. Until the indexing task is complete, the index is an "inactive" index.

To check whether an index is "active", run the following query (replacing index_name with the name of the index that you want to check):

Select("active", Get(Index("index_name")))

If you see true in the output, the index is "active" and is ready for your queries. Otherwise, you should wait and check again later, until true appears in the output.

The following query creates an index for the collection "spells" with the name "new-index":

client.Query(
  CreateIndex(
    Obj("name", "new-index", "source", Collection("spells"))));
{
  "ref": { "@ref": "indexes/new-index" },
  "class": { "@ref": "indexes" },
  "ts": 1509244540009619,
  "active": false,
  "partitions": 8,
  "name": "new-index",
  "source": { "@ref": "classes/spells" }
}
curl https://db.fauna.com/ \
    -u fnAChGwBcAACAO70ziE0cfROosNJHdgBmJU1PgpL: \
    -d '{
          "create_index": {
            "object": { "name": "new-index", "source": { "collection": "spells" } }
          }
        }'
HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "indexes/new-index" },
    "class": { "@ref": "indexes" },
    "ts": 1509244540009619,
    "active": false,
    "partitions": 8,
    "name": "new-index",
    "source": { "@ref": "classes/spells" }
  }
}
result, _ := client.Query(
    f.CreateIndex(
        f.Obj{"name": "new-index", "source": f.Collection("spells")},
    ),
)

fmt.Println(result)
map[ref:{new-index 0xc4201ef8e0 <nil>} ts:1509244540009619 active:false partitions:8 name:new-index source:{spells 0xc4201efb40 <nil>}]
System.out.println(
      client.query(
          CreateIndex(
              Obj(
                  "name", Value("new-index"),
                  "source", Collection(Value("spells"))
              )
          )
      ).get());
{
  ref: ref(id = "new-index", collection = ref(id = "indexes")),
  ts: 1526674566835735,
  active: false,
  partitions: 8,
  name: "new-index",
  source: ref(id = "spells", collection = ref(id = "collections"))
}
client.query(
  q.CreateIndex({
    name: 'new-index',
    source: q.Collection('spells'),
  })
)
.then((ret) => console.log(ret))
{ ref: Ref(id=new-index, collection=Ref(id=indexes)),
  ts: 1527275052756370,
  active: false,
  partitions: 8,
  name: 'new-index',
  source: Ref(id=spells, collection=Ref(id=collections)) }
client.query(
  q.create_index(
    {"name": "new-index", "source": q.collection("spells")}
  ))
{
  "ref": { "@ref": "indexes/new-index" },
  "class": { "@ref": "indexes" },
  "ts": 1509244540009619,
  "active": false,
  "partitions": 8,
  "name": "new-index",
  "source": { "@ref": "classes/spells" }
}
client.query(
  CreateIndex(
    Obj("name" -> "new-index", "source" -> Collection("spells"))))
{
  "ref": { "@ref": "indexes/new-index" },
  "class": { "@ref": "indexes" },
  "ts": 1509244540009619,
  "active": false,
  "partitions": 8,
  "name": "new-index",
  "source": { "@ref": "classes/spells" }
}

Modifying index documents

It is possible to rename an index by updating its name field. Renaming an index changes its Reference, but preserves inbound References to the index. Index data is not rebuilt.

An index’s terms and values fields may not be changed. If you require such a change, the existing index must be deleted and a new one created using the new definitions for terms and/or `values.

If you update the unique field, existing duplicate items are not removed from the index.

When an index is deleted, it becomes inaccessible, and its data is deleted asynchronously.

Reading indexes

Entries in an index have zero or more terms, and zero or more values.

Entries are partitioned into sets by their defined terms fields, which is a strategy to improve index performance. Within each set, entries are sorted by their defined values fields.

The Match function is used to refer to a set of entries within an index:

client.Query(Match(Index("spells_by_element"), "fire"));
curl https://db.fauna.com/ \
    -u fnACrVIrDDACAFiX3FN4PhwADpl7dtPRhWObP08j: \
    -d '{ "match": { "index": "spells_by_element" }, "terms": "fire" }'
result, _ := client.Query(f.MatchTerm(f.Index("spells_by_element"), "fire"))

fmt.Println(result)
{map[match:{spells_by_element 0xc4203be2c0 <nil>} terms:fire]}
System.out.println(
        client.query(
           Match(
              Index(Value("spells_by_element")),
              Value("fire"))
        ).get());
{
  @set = {
    match: ref(id = "spells_by_element", collection = ref(id = "indexes")), 
    terms: "fire"
  }
}
client.query(
  q.Match(q.Index('spells_by_element'), 'fire')
)
.then((ret) => console.log(ret))
SetRef({"match":{"@ref":{"id":"spells_by_element","class":{"@ref":{"id":"indexes"}}}},"terms":"fire"})
client.query(q.match(q.index("spells_by_element"), "fire"))
$client.query do
  match index('spells_by_element'), 'fire'
end
client.query(Match(Index("spells_by_element"), "fire"))
client.query(
    Match(index: Index("spells_by_element"), terms: "fire")
)

If the index is configured to index multiple terms (also called a compound index), Match should be passed an Array having the required number of term values:

client.Query(
  Match(
    Index("spells_by_element_and_name"),
    Arr("fire", "Fire Beak")));
curl https://db.fauna.com/ \
    -u fnACrVIrDDACAFiX3FN4PhwADpl7dtPRhWObP08j: \
    -d '{
          "match": { "index": "spells_by_element_and_name" },
          "terms": [ "fire", "Fire Beak" ]
        }'
result, _ := client.Query(
    f.MatchTerm(
        f.Index("spells_by_element_and_name"),
        f.Arr{"fire", "Fire Beak"},
    ),
)

fmt.Println(result)
{map[terms:[fire Fire Beak] match:{spells_by_element_and_name 0xc4203b46c0 <nil>}]}
System.out.println(
        client.query(
           Match(
             Index(Value("spells_by_element_and_name")),
             Arr(Value("fire"), Value("Fire Beak"))
           )
        ).get());
{
  @set = {
    match: ref(id = "spells_by_element_and_name", collection = ref(id = "indexes")), 
    terms: ["fire", "Fire Beak"]
  }
}
client.query(
  q.Match(
    q.Index('spells_by_element_and_name'),
    ['fire', 'Fire Beak'],
  )
)
.then((ret) => console.log(ret))
SetRef({"match":{"@ref":{"id":"spells_by_element_and_name","class":{"@ref":{"id":"indexes"}}}},"terms":["fire","Fire Beak"]})
client.query(
  q.match(
    q.index("spells_by_element_and_name"),
    ["fire", "Fire Beak"]
  ))
$client.query do
  match index('spells_by_element_and_name'),
        ['fire', 'Fire Beak']
end
client.query(
  Match(
    Index("spells_by_element_and_name"),
    Arr("fire", "Fire Beak")))
client.query(
    Match(
        index: Index("spells_by_element_and_name"),
        terms: "fire", "Fire Beak"
    )
)

Or conversely, if the index is configured with no terms, then only the index Reference needs be provided:

client.Query(Match(Index("all_spells")));
{ "@set": { "match": { "@ref": "indexes/all_spells" } } }
curl https://db.fauna.com/ \
    -u fnACrVIrDDACAFiX3FN4PhwADpl7dtPRhWObP08j: \
    -d '{ "match": { "index": "all_spells" } }'
HTTP/1.1 200 OK
{
  "resource": { "@set": { "match": { "@ref": "indexes/all_spells" } } }
}
result, _ := client.Query(f.Match(f.Index("all_spells")))

fmt.Println(result)
{map[match:{all_spells 0xc420399180 <nil>}]}
System.out.println(
    client.query(Match(Index(Value("all_spells"))))
    .get());
{ @set = {match: ref(id = "all_spells", collection = ref(id = "indexes"))} }
client.query(
  q.Match(q.Index('all_spells'))
)
.then((ret) => console.log(ret))
SetRef({"match":{"@ref":{"id":"all_spells","class":{"@ref":{"id":"indexes"}}}}})
client.query(q.match(q.index("all_spells")))
{ "@set": { "match": { "@ref": "indexes/all_spells" } } }
$client.query do
  match index('all_spells')
end
{ "@set": { "match": { "@ref": "indexes/all_spells" } } }
client.query(Match(Index("all_spells")))
{ "@set": { "match": { "@ref": "indexes/all_spells" } } }
client.query(Match(index: Index("all_spells")))
{ "@set": { "match": { "@ref": "indexes/all_spells" } } }

Index terms are always scalar values, and Match interprets Arrays as tuples. For single-term indexes, the following expressions are equivalent:

client.Query(Match(Index("spells_by_element"), "fire"));
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}
curl https://db.fauna.com/ \
    -u fnACrVIrDDACAFiX3FN4PhwADpl7dtPRhWObP08j: \
    -d '{ "match": { "index": "spells_by_element" }, "terms": "fire" }'
HTTP/1.1 200 OK
{
  "resource": {
    "@set": {
      "match": { "@ref": "indexes/spells_by_element" },
      "terms": "fire"
    }
  }
}
result, _ := client.Query(f.MatchTerm(f.Index("spells_by_element"), "fire"))

fmt.Println(result)
{map[match:{spells_by_element 0xc4203b0680 <nil>} terms:fire]}
System.out.println(
    client.query(
      Match(Index(Value("spells_by_element")), Value("fire"))
    ).get());
{
  @set = {
    match: ref(id = "spells_by_element", collection = ref(id = "indexes")), 
    terms: "fire"
  }
}
client.query(
  q.Match(q.Index('spells_by_element'), 'fire')
)
.then((ret) => console.log(ret))
SetRef({"match":{"@ref":{"id":"spells_by_element","class":{"@ref":{"id":"indexes"}}}},"terms":"fire"})
client.query(q.match(q.index("spells_by_element"), "fire"))
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}
$client.query do
  match index('spells_by_element'), 'fire'
end
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}
client.query(Match(Index("spells_by_element"), "fire"))
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}
client.query(
    Match(index: Index("spells_by_element"), terms: "fire")
)
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}
client.Query(Match(Index("spells_by_element"), Arr("fire")));
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}
curl https://db.fauna.com/ \
    -u fnACrVIrDDACAFiX3FN4PhwADpl7dtPRhWObP08j: \
    -d '{
          "match": { "index": "spells_by_element" },
          "terms": [ "fire" ]
        }'
HTTP/1.1 200 OK
{
  "resource": {
    "@set": {
      "match": { "@ref": "indexes/spells_by_element" },
      "terms": "fire"
    }
  }
}
result, _ := client.Query(
    f.MatchTerm(f.Index("spells_by_element"), f.Arr{"fire"}),
)

fmt.Println(result)
{map[match:{spells_by_element 0xc42038d940 <nil>} terms:fire]}
System.out.println(
        client.query(
           Match(Index(Value("spells_by_element")), Arr(Value("fire")))
        ).get());
{
  @set = {
    match: ref(id = "spells_by_element", collection = ref(id = "indexes")), 
    terms: "fire"
  }
}
client.query(
  q.Match(q.Index('spells_by_element'), ['fire'])
)
.then((ret) => console.log(ret))
SetRef({"match":{"@ref":{"id":"spells_by_element","class":{"@ref":{"id":"indexes"}}}},"terms":"fire"})
client.query(q.match(q.index("spells_by_element"), ["fire"]))
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}
$client.query do
  match index('spells_by_element'), ['fire']
end
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}
client.query(Match(Index("spells_by_element"), Arr("fire")))
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}
client.query(
    Match(index: Index("spells_by_element"), terms: "fire")
)
{
  "@set": {
    "match": { "@ref": "indexes/spells_by_element" },
    "terms": "fire"
  }
}

Ordering

Results from indexes are sorted lexically according to their type. The primary sort is based on the first field defined in the index’s values field. Results are sub-sorted according to each subsequent values field (if any), in turn.

Strings and Numbers sort using their natural order, while Arrays and Objects sort according to their contents. For example, { "name": "Hen Wen" } appears after { }, and { "age": 110 }.

When no values fields are defined, the index is sorted by each indexed document’s reference.

Documents may have different types of field values in the same field, or a document may be missing a field entirely. An index sorts values in this order: Numbers, Strings, Refs, Timestamps, Dates, Booleans, Nulls. Note that Objects and Arrays are not indexed, although the fields of an object can be indexed.

The default sort order may be reversed on a per-field basis using the reverse flag in the index configuration.

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!