Automatically add createdAt and updatedAt on each records?

I have

client.query(
  q.Create(
    q.Collection('users'),
    {
      data: {
        email,
        password,
        lastLogin: null,
        updatedAt: new Date(),
        createdAt: new Date()
      }
    }
  )
);

can updatedAt and createdAt be added and managed automatically so I don’t have to specify it?

updatedAt is the same as ts, and created at can be fetched by getting the ts from the first event. The downside is that it will require another read. That being said you could easily create your own “create” replacement using nothing but FQL.

const CreateCustom = (col, obj) => {
    return q.Let(
        { obj },
        q.Create(
            col,
            q.Merge(q.Var("obj"), {
                data: q.Merge(q.Select(["data"], q.Var("obj"), {}), {
                    createdAt: q.Now(),
                    updatedAt: q.Now(),
                }),
            })
        )
    )
}

const UpdateCustom = (ref, obj) => {
    return q.Let(
        { obj },
        q.Update(
            ref,
            q.Merge(q.Var("obj"), {
                data: q.Merge(q.Select(["data"], q.Var("obj"), {}), {
                    updatedAt: q.Now(),
                }),
            })
        )
    )
}

So, currently, no way to do this / enable this on fauna db side?

Not as I am aware. I’m using the built in ts for both createdAt and updatedAt.

@ptpaterson do you know of anyway to achieve this in graphql? automatically add these ts without needing to refer to the ts and the ts from the first event.

There is no built-in way to add a default createdAt field. This is a good feature request, in my opinion. I know a built-in createdAt field would be helpful to a number of folks.

Until then, a custom resolver is the way to go to provide a “create” mutation with default values.

Other considerations

the ts value is the last updated timestamp, so there is no need to create another field. If you application only creates and does not do additional updates, then you can use the ts value as the created timestamp (ts is literally the timestamp for the Document’s “create” event). But just remember that as soon as your application writes to a Document, the latest ts changes.

Some people have tried to use Document history to query the “create” event, but that can be more expensive in the long run (extra Read Ops, storage), and is a lot of additional code to maintain. In general, I would not recommend this. But folks may find interesting ways to leverage Fauna’s temporality efficiently.

On using TS as updated at

Yes, one can use the TS as the updatedAt field but we actually don’t get that when we use graphql, unless we create custom resolvers which adds more work because now we’ll have to create custom resolvers for our get and list queries just to grab the TS and add it as updatedAt field, unless fauna changes the default mutations and queries to add the TS as the updatedAt field.

On creating custom resolvers for the createdAt

This workaround will do the work but will again require that we create custom resolvers for each of our documents, unless we have a way to provide a custom create function for each predefined mutations without us need to attach a custom resolver for each of our mutation for our collection.

I’m thinking of something like:

email: String
fullName: String
updatedAt: UpdateTS <-- fauna identifies this and adds the ts as updatedAt on queries
createdAt: CreateTS <-- fauna identifies this and adds ts on `create` mutation

The generated GraphQL schema includes a _ts field for all non-embedded types.

findThingByID(id: "1234") {
  _id
  _ts
}

You can even alias it if you want:

findThingByID(id: "310629044113637440") {
  _id
  updatedAt: _ts
}


// result
{
  "data": {
    "findThingByID": {
      "_id": "310629044113637440",
      "updatedAt": 1632497791340000
    }
  }
}

Otherwise, I agree that it is not a great experience to require a custom Create resolver for every type that you want a createdAt field.