It's possible to have Fauna sequentially execute expressions using Do
. However, it doesn't work in this particular case:
Do(
CreateCollection({ name: "users" }),
CreateIndex({
name: "users_by_email",
permissions: { read: "public" },
source: Collection("users"),
terms: [{field: ["data", "email"]}],
unique: true
})
)
I think this is because "The index [...] may not be created in the same transaction as its source collection(s)." https://docs.fauna.com/fauna/current/api/fql/functions/createindex?lang=javascript
How can I efficiently submit my collection and index creation commands together in the one request?
To answer the title question directly: No. One "request" is a transaction.
However, as you have noted, it is possible to execute multiple FQL expressions in a single transaction, such as your use of the Do
function.
The reason that the Do
function doesn't work for your example is that the Fauna query executor performs reads and aggregates write intentions as the transaction expression is evaluated, but all write effects happen at the end of the transaction. That means that the collection has not been fully written at the time that your CreateIndex
expression is evaluated, so there is no Collection("users")
in existence when it is needed.
That is why the warning in the documentation exists. You need to create the collection in one transaction, and the index in another. If you are deploying a known schema, you can create all of your collections in a single transaction, and all of your indexes in a second. That's the best practice answer.
However, it is currently possible with API v4 to make this work by using the Let
function:
Let(
{
collection: CreateCollection({ name: "users" }),
collection_ref: Select("ref", Var("collection")),
},
CreateIndex({
name: "users_by_email",
source: Var("collection_ref"),
terms: [{field: ["data", "email"]}],
unique: true,
})
)
The reason that this works is that the source
field for an index needs a valid reference. By capturing the result of CreateCollection
in a named variable, the reference can be be used in the CreateIndex
expression via the variable.
In the future, the query executor will likely be upgraded to verify the legitimacy of all references provided by variables in the source
field. If/when that happens, this technique will no longer work. Use this technique at your own risk.