01 Tutorials

Languages:

Introduction

Every instance has an associated history that is maintained as far back as its class’s history_days. This allows you to view and edit all events that happened to the instance, as well as the state of the instance after each event. This ability to edit both the current data and the history of the data is known as bitemporality.

This means you can do things like:

  • Diagnose errors by viewing all changes made to an instance.
  • Correct erroneous data by erasing it from history.
  • Keep historical data up-to-date with current information; for example, to indicate that a customer made a payment before a due date even if the data is entered after that date.

Example

In this example we will model a car dealer. The dealer keeps track of each car’s model, license plate, and price.

Setup

Create a Class


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{ "create_class": { "object": { "name": "cars" } } }'

client.query(CreateClass(Obj("name", Value("cars"))));

client.query(q.CreateClass({ name: "cars" }));

client.query(CreateClass(Obj("name" -> "cars")))

$client.query do
  create_class name: 'cars'
end

client.Query(CreateClass(Obj("name", "cars")));

client.query(q.create_class({"name": "cars"}))

client.Query(f.CreateClass(f.Obj{"name": "cars"}))

client.query(CreateClass(Obj("name" => "cars")))

HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "classes/cars" },
    "class": { "@ref": "classes" },
    "ts": 1436375112141542,
    "history_days": 30,
    "name": "cars"
  }
}

=> {
  "ref": { "@ref": "classes/cars" },
  "class": { "@ref": "classes" },
  "ts": 1436375112141542,
  "history_days": 30,
  "name": "cars"
}

=> {
  "ref": { "@ref": "classes/cars" },
  "class": { "@ref": "classes" },
  "ts": 1436375112141542,
  "history_days": 30,
  "name": "cars"
}

=> {
  "ref": { "@ref": "classes/cars" },
  "class": { "@ref": "classes" },
  "ts": 1436375112141542,
  "history_days": 30,
  "name": "cars"
}

=> {
  "ref": { "@ref": "classes/cars" },
  "class": { "@ref": "classes" },
  "ts": 1436375112141542,
  "history_days": 30,
  "name": "cars"
}

=> {
  "ref": { "@ref": "classes/cars" },
  "class": { "@ref": "classes" },
  "ts": 1436375112141542,
  "history_days": 30,
  "name": "cars"
}

=> {
  "ref": { "@ref": "classes/cars" },
  "class": { "@ref": "classes" },
  "ts": 1436375112141542,
  "history_days": 30,
  "name": "cars"
}

=> {
  "ref": { "@ref": "classes/cars" },
  "class": { "@ref": "classes" },
  "ts": 1436375112141542,
  "history_days": 30,
  "name": "cars"
}

=> {
  "ref": { "@ref": "classes/cars" },
  "class": { "@ref": "classes" },
  "ts": 1436375112141542,
  "history_days": 30,
  "name": "cars"
}

Create an Instance

Creating an instance will be the first event that happens to it. All events that don’t delete the instance will be “create” events, including updates.


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "create": { "class": "cars" },
          "params": {
            "object": {
              "data": {
                "object": {
                  "model": "mustang",
                  "license": "EATMYDUST",
                  "price": 40000
                }
              }
            }
          }
        }'

client.query(
  Create(
    Class(Value("cars")),
    Obj(
      "data", Obj(
        "model", Value("mustang"),
        "license", Value("EATMYDUST"),
        "price", Value(40000)
      )
    )));

client.query(
  q.Create(
    q.Class("cars"),
    {
      data: { model: "mustang", license: "EATMYDUST", price: 40000 }
    }));

client.query(
  Create(
    Class("cars"),
    Obj(
      "data" -> Obj(
        "model" -> "mustang",
        "license" -> "EATMYDUST",
        "price" -> 40000
      )
    )))

$client.query do
  create class_('cars'),
         data: { model: 'mustang', license: 'EATMYDUST', price: 40000 }
end

client.Query(
  Create(
    Class("cars"),
    Obj(
      "data", Obj(
        "model", "mustang",
        "license", "EATMYDUST",
        "price", 40000
      )
    )));

client.query(
  q.create(
    q.class_expr("cars"),
    {
      "data": {"model": "mustang", "license": "EATMYDUST", "price": 40000}
    }
  ))

client.Query(
    f.Create(
        f.Class("cars"),
        f.Obj{
            "data": f.Obj{
                "model": "mustang",
                "license": "EATMYDUST",
                "price": 40000,
            },
        },
    ),
)

client.query(
    Create(
        at: Class("cars"),
        Obj(
            "data" => Obj(
                "model" => "mustang",
                "license" => "EATMYDUST",
                "price" => 40000
            )
        )
    )
)

HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "classes/cars/104979509692858368" },
    "class": { "@ref": "classes/cars" },
    "ts": 1436375112316028,
    "data": {
      "model": "mustang",
      "license": "EATMYDUST",
      "price": 40000
    }
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

Change the Instance

Let’s mark up the price. Since this is an update, this becomes an event as well.


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "update": { "@ref": "classes/cars/104979509692858368" },
          "params": { "object": { "data": { "object": { "price": 50000 } } } }
        }'

client.query(
  Update(
    Ref("classes/cars/104979509692858368"),
    Obj("data", Obj("price", Value(50000)))));

client.query(
  q.Update(
    Ref("classes/cars/104979509692858368"),
    { data: { price: 50000 } }));

client.query(
  Update(
    Ref("classes/cars/104979509692858368"),
    Obj("data" -> Obj("price" -> 50000))))

$client.query do
  update ref('classes/cars/104979509692858368'),
         data: { price: 50000 }
end

client.Query(
  Update(
    Ref("classes/cars/104979509692858368"),
    Obj("data", Obj("price", 50000))));

client.query(
  q.update(
    Ref("classes/cars/104979509692858368"),
    {"data": {"price": 50000}}
  ))

client.Query(
    f.Update(
        f.Ref("classes/cars/104979509692858368"),
        f.Obj{"data": f.Obj{"price": 50000}},
    ),
)

client.query(
    Update(
        ref: Ref("classes/cars/104979509692858368"),
        to: Obj("data" => Obj("price" => 50000))
    )
)

HTTP/1.1 200 OK
{
  "resource": {
    "ref": { "@ref": "classes/cars/104979509692858368" },
    "class": { "@ref": "classes/cars" },
    "ts": 1436375112374190,
    "data": {
      "model": "mustang",
      "license": "EATMYDUST",
      "price": 50000
    }
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112374190,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 50000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112374190,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 50000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112374190,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 50000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112374190,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 50000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112374190,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 50000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112374190,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 50000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112374190,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 50000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112374190,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 50000
  }
}

View History

View Events

Suppose you didn’t intend for the price to go up and want to find out when that happened.

To view the events of a single instance, paginate over its ref with "events": true.


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "paginate": { "@ref": "classes/cars/104979509692858368" },
          "events": true
        }'

client.query(
  Paginate(Ref("classes/cars/104979509692858368"))
    .events(Value(true)));

client.query(
  q.Paginate(
    Ref("classes/cars/104979509692858368"),
    { events: true }));

client.query(
  Paginate(
    Ref("classes/cars/104979509692858368"),
    events = true))

$client.query do
  paginate ref('classes/cars/104979509692858368'), events: true
end

client.Query(
  Paginate(Ref("classes/cars/104979509692858368"), events: true));

client.query(
  q.paginate(
    Ref("classes/cars/104979509692858368"),
    events=True
  ))

client.Query(
    f.Paginate(
        f.Ref("classes/cars/104979509692858368"),
        f.Events(true),
    ),
)

client.query(
    Paginate(
        Ref("classes/cars/104979509692858368"),
        events: true
    )
)

HTTP/1.1 200 OK
{
  "resource": {
    "data": [
      {
        "ts": 1436375112316028,
        "action": "create",
        "resource": { "@ref": "classes/cars/104979509692858368" }
      },
      {
        "ts": 1436375112374190,
        "action": "create",
        "resource": { "@ref": "classes/cars/104979509692858368" }
      }
    ]
  }
}

=> {
  "data": [
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112374190,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112374190,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112374190,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112374190,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112374190,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112374190,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112374190,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112374190,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

View Past Data

That’s not very helpful. The set of events only tells you when events were, not what they were.

To view event data, we map a get over every event.

Normally when you get a ref, the most recent version is used. You can override this by specifying ts to the time of an event.


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "map": {
            "lambda": "event",
            "expr": {
              "get": { "select": "resource", "from": { "var": "event" } },
              "ts": { "select": "ts", "from": { "var": "event" } }
            }
          },
          "collection": {
            "paginate": { "@ref": "classes/cars/104979509692858368" },
            "events": true
          }
        }'

client.query(
  Map(
    Paginate(Ref("classes/cars/104979509692858368"))
      .events(Value(true)),
    Lambda(
      Value("event"),
      Get(
        Select(Value("resource"), Var("event")),
        Select(Value("ts"), Var("event"))))));

client.query(
  q.Map(
    q.Paginate(
      Ref("classes/cars/104979509692858368"),
      { events: true }),
    function(event) {
      return q.Get(q.Select("resource", event), q.Select("ts", event));
    }));

client.query(
  Map(
    Paginate(
      Ref("classes/cars/104979509692858368"),
      events = true),
    Lambda { event =>
      Get(Select("resource", event), Select("ts", event))
    }))

$client.query do
  map paginate(ref('classes/cars/104979509692858368'),
           events: true) do |event|
    get(select('resource', event), select('ts', event))
  end
end

client.Query(
  Map(
    Paginate(
      Ref("classes/cars/104979509692858368"),
      events: true),
    event => Get(Select("resource", event), Select("ts", event))));

client.query(
  q.map_expr(
    lambda event: q.get(q.select("resource", event), q.select("ts", event)),
    q.paginate(
      Ref("classes/cars/104979509692858368"),
      events=True
    )
  ))

client.Query(
    f.Map(
        f.Paginate(
            f.Ref("classes/cars/104979509692858368"),
            f.Events(true),
        ),
        f.Lambda(
            "event",
            f.Get(
                f.Select("resource", f.Var("event")),
                f.Select("ts", f.Var("event")),
            ),
        ),
    ),
)

client.query(
    Map(
        collection: Paginate(
            Ref("classes/cars/104979509692858368"),
            events: true
        ),
        to: { event in
            Get(
                Select(path: "resource", from: event),
                ts: Select(path: "ts", from: event)
            )
        }
    )
)

HTTP/1.1 200 OK
{
  "resource": {
    "data": [
      {
        "ref": { "@ref": "classes/cars/104979509692858368" },
        "class": { "@ref": "classes/cars" },
        "ts": 1436375112316028,
        "data": {
          "model": "mustang",
          "license": "EATMYDUST",
          "price": 40000
        }
      },
      {
        "ref": { "@ref": "classes/cars/104979509692858368" },
        "class": { "@ref": "classes/cars" },
        "ts": 1436375112374190,
        "data": {
          "model": "mustang",
          "license": "EATMYDUST",
          "price": 50000
        }
      }
    ]
  }
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 40000
      }
    },
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112374190,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 50000
      }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 40000
      }
    },
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112374190,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 50000
      }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 40000
      }
    },
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112374190,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 50000
      }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 40000
      }
    },
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112374190,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 50000
      }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 40000
      }
    },
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112374190,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 50000
      }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 40000
      }
    },
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112374190,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 50000
      }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 40000
      }
    },
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112374190,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 50000
      }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 40000
      }
    },
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112374190,
      "data": {
        "model": "mustang",
        "license": "EATMYDUST",
        "price": 50000
      }
    }
  ]
}

Changing Events

Remove Events

When you delete the most recent event, instance data reverts to a previous version.

You can use the data you just collected to find and remove the event that raised the price.


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "remove": { "@ref": "classes/cars/104979509692858368" },
          "ts": 1436375112374190,
          "action": "create"
        }'

client.query(
  Remove(
    Ref("classes/cars/104979509692858368"),
    Value(1436375112374190),
    Action.CREATE));

client.query(
  q.Remove(
    Ref("classes/cars/104979509692858368"),
    1436375112374190,
    "create"));

client.query(
  Remove(
    Ref("classes/cars/104979509692858368"),
    ts = 1436375112374190,
    action = "create"))

$client.query do
  remove ref('classes/cars/104979509692858368'),
         1436375112374190,
         'create'
end

client.Query(
  Remove(
    Ref("classes/cars/104979509692858368"),
    ts: 1436375112374190,
    action: "create"));

client.query(
  q.remove(
    Ref("classes/cars/104979509692858368"),
    ts=1436375112374190,
    action="create"
  ))

client.Query(
    f.Remove(
        f.Ref("classes/cars/104979509692858368"),
        1436375112374190,
        f.ActionCreate,
    ),
)

client.query(
    Remove(
        ref: Ref("classes/cars/104979509692858368"),
        ts: 1436375112374190,
        action: "create"
    )
)

HTTP/1.1 200 OK
{ "resource": null }

=> null

=> null

=> null

=> null

=> null

=> null

=> null

=> null

When you next get the instance it will be back to its original state.


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{ "get": { "@ref": "classes/cars/104979509692858368" } }'

client.query(Get(Ref("classes/cars/104979509692858368")));

client.query(q.Get(Ref("classes/cars/104979509692858368")));

client.query(Get(Ref("classes/cars/104979509692858368")))

$client.query do
  get ref('classes/cars/104979509692858368')
end

client.Query(Get(Ref("classes/cars/104979509692858368")));

client.query(q.get(Ref("classes/cars/104979509692858368")))

client.Query(f.Get(f.Ref("classes/cars/104979509692858368")))

client.query(Get(Ref("classes/cars/104979509692858368")))

HTTP/1.1 200 OK
{
  "resource": {
    "ref": { "@ref": "classes/cars/104979509692858368" },
    "class": { "@ref": "classes/cars" },
    "ts": 1436375112316028,
    "data": {
      "model": "mustang",
      "license": "EATMYDUST",
      "price": 40000
    }
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112316028,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 40000
  }
}

If you remove an event other than the most recent one, it will disappear from the event history, but the current value of the instance will be unchanged. This is useful if you know that the event was an error and want a clean history.

Removing an event is a very different thing from adding a delete event! Removing an event means the instance at that event’s ts will revert to its state at the previous event. Adding a delete event means that the instance at that event’s ts time will be considered nonexistent.

Insert Events

It’s also possible to insert any event at any point in the past. You can use this to add new information about the past. For example, suppose you discover that the car was on sale before the first record of it, and at a lower price.


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "insert": { "@ref": "classes/cars/104979509692858368" },
          "ts": 1436375112199704,
          "action": "create",
          "params": {
            "let": {
              "current": { "get": { "@ref": "classes/cars/104979509692858368" } }
            },
            "in": {
              "object": {
                "data": {
                  "object": {
                    "model": {
                      "select": [ "data", "model" ],
                      "from": { "var": "current" }
                    },
                    "license": {
                      "select": [ "data", "license" ],
                      "from": { "var": "current" }
                    },
                    "price": 30000
                  }
                }
              }
            }
          }
        }'

client.query(
  Insert(
    Ref("classes/cars/104979509692858368"),
    Value(1436375112199704),
    Action.CREATE,
    Let(
      "current", Get(Ref("classes/cars/104979509692858368"))
    ).in(
      Obj(
        "data", Obj(
          "model", Select(Arr(Value("data"), Value("model")), Var("current")),
          "license", Select(
            Arr(Value("data"), Value("license")),
            Var("current")),
          "price", Value(30000)
        )
      )
    )));

client.query(
  q.Insert(
    Ref("classes/cars/104979509692858368"),
    1436375112199704,
    "create",
    q.Let(
      { current: q.Get(Ref("classes/cars/104979509692858368")) },
      {
        data: {
          model: q.Select(["data", "model"], q.Var("current")),
          license: q.Select(["data", "license"], q.Var("current")),
          price: 30000
        }
      })));

client.query(
  Insert(
    Ref("classes/cars/104979509692858368"),
    ts = 1436375112199704,
    action = "create",
    params = Let {
      val current = Get(Ref("classes/cars/104979509692858368"))
      Obj(
        "data" -> Obj(
          "model" -> Select(Arr("data", "model"), current),
          "license" -> Select(Arr("data", "license"), current),
          "price" -> 30000
        )
      )
    }))

$client.query do
  insert ref('classes/cars/104979509692858368'),
         1436375112199704,
         'create',
         let(current: get(ref('classes/cars/104979509692858368'))) do
           data: {
             model: select(['data', 'model'], current),
             license: select(['data', 'license'], current),
             price: 30000
           }
         end
end

client.Query(
  Insert(
    Ref("classes/cars/104979509692858368"),
    ts: 1436375112199704,
    action: "create",
    @params: Let(
      Obj("current", Get(Ref("classes/cars/104979509692858368"))),
      Obj(
        "data", Obj(
          "model", Select(Arr("data", "model"), Var("current")),
          "license", Select(Arr("data", "license"), Var("current")),
          "price", 30000
        )
      ))));

client.query(
  q.insert(
    Ref("classes/cars/104979509692858368"),
    ts=1436375112199704,
    action="create",
    params=q.let(
      {"current": q.get(Ref("classes/cars/104979509692858368"))},
      {
        "data": {
          "model": q.select(["data", "model"], q.var("current")),
          "license": q.select(["data", "license"], q.var("current")),
          "price": 30000
        }
      }
    )
  ))

client.Query(
    f.Insert(
        f.Ref("classes/cars/104979509692858368"),
        1436375112199704,
        f.ActionCreate,
        f.Let(
            f.Obj{
                "current": f.Get(f.Ref("classes/cars/104979509692858368")),
            },
            f.Obj{
                "data": f.Obj{
                    "model": f.Select(f.Arr{"data", "model"}, f.Var("current")),
                    "license": f.Select(f.Arr{"data", "license"}, f.Var("current")),
                    "price": 30000,
                },
            },
        ),
    ),
)

client.query(
    Insert(
        ref: Ref("classes/cars/104979509692858368"),
        ts: 1436375112199704,
        action: "create",
        params: Let(
            bindings: [
            current: Get(Ref("classes/cars/104979509692858368"))
            ],
            in: Obj(
                "data" => Obj(
                    "model" => Select(
                        path: "data", "model",
                        from: Var("current")
                    ),
                    "license" => Select(
                        path: "data", "license",
                        from: Var("current")
                    ),
                    "price" => 30000
                )
            )
        )
    )
)

HTTP/1.1 200 OK
{
  "resource": {
    "ts": 1436375112199704,
    "action": "create",
    "resource": { "@ref": "classes/cars/104979509692858368" }
  }
}

=> {
  "ts": 1436375112199704,
  "action": "create",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112199704,
  "action": "create",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112199704,
  "action": "create",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112199704,
  "action": "create",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112199704,
  "action": "create",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112199704,
  "action": "create",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112199704,
  "action": "create",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112199704,
  "action": "create",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

The event data is fetchable using the ts specified.


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "get": { "@ref": "classes/cars/104979509692858368" },
          "ts": 1436375112199704
        }'

client.query(
  Get(
    Ref("classes/cars/104979509692858368"),
    Value(1436375112199704)));

client.query(
  q.Get(
    Ref("classes/cars/104979509692858368"),
    1436375112199704));

client.query(
  Get(Ref("classes/cars/104979509692858368"), 1436375112199704))

$client.query do
  get ref('classes/cars/104979509692858368'), 1436375112199704
end

client.Query(
  Get(Ref("classes/cars/104979509692858368"), 1436375112199704));

client.query(
  q.get(
    Ref("classes/cars/104979509692858368"),
    1436375112199704
  ))

client.Query(
    f.Get(
        f.Ref("classes/cars/104979509692858368"),
        1436375112199704,
    ),
)

client.query(
    Get(
        Ref("classes/cars/104979509692858368"),
        ts: 1436375112199704
    )
)

HTTP/1.1 200 OK
{
  "resource": {
    "ref": { "@ref": "classes/cars/104979509692858368" },
    "class": { "@ref": "classes/cars" },
    "ts": 1436375112199704,
    "data": {
      "model": "mustang",
      "license": "EATMYDUST",
      "price": 30000
    }
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112199704,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 30000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112199704,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 30000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112199704,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 30000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112199704,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 30000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112199704,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 30000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112199704,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 30000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112199704,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 30000
  }
}

=> {
  "ref": { "@ref": "classes/cars/104979509692858368" },
  "class": { "@ref": "classes/cars" },
  "ts": 1436375112199704,
  "data": {
    "model": "mustang",
    "license": "EATMYDUST",
    "price": 30000
  }
}

You can also add delete events at any point to indicate that the instance was missing for some time period. The next create event implies a resurrection of the instance. (Resurrection may be preferable to undoing a deletion — for example, to indicate that a customer closed and re-opened their account.)


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "insert": { "@ref": "classes/cars/104979509692858368" },
          "ts": 1436375112257866,
          "action": "delete"
        }'

client.query(
  Insert(
    Ref("classes/cars/104979509692858368"),
    Value(1436375112257866),
    Action.DELETE));

client.query(
  q.Insert(
    Ref("classes/cars/104979509692858368"),
    1436375112257866,
    "delete"));

client.query(
  Insert(
    Ref("classes/cars/104979509692858368"),
    ts = 1436375112257866,
    action = "delete"))

$client.query do
  insert ref('classes/cars/104979509692858368'),
         1436375112257866,
         'delete'
end

client.Query(
  Insert(
    Ref("classes/cars/104979509692858368"),
    ts: 1436375112257866,
    action: "delete"));

client.query(
  q.insert(
    Ref("classes/cars/104979509692858368"),
    ts=1436375112257866,
    action="delete"
  ))

client.Query(
    f.Insert(
        f.Ref("classes/cars/104979509692858368"),
        1436375112257866,
        f.ActionDelete,
    ),
)

client.query(
    Insert(
        ref: Ref("classes/cars/104979509692858368"),
        ts: 1436375112257866,
        action: "delete"
    )
)

HTTP/1.1 200 OK
{
  "resource": {
    "ts": 1436375112257866,
    "action": "delete",
    "resource": { "@ref": "classes/cars/104979509692858368" }
  }
}

=> {
  "ts": 1436375112257866,
  "action": "delete",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112257866,
  "action": "delete",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112257866,
  "action": "delete",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112257866,
  "action": "delete",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112257866,
  "action": "delete",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112257866,
  "action": "delete",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112257866,
  "action": "delete",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

=> {
  "ts": 1436375112257866,
  "action": "delete",
  "resource": { "@ref": "classes/cars/104979509692858368" }
}

The instance data will not be retrievable at that point in time. (It is still there in the present if, as in this case, the delete is not the most recent event.)


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "get": { "@ref": "classes/cars/104979509692858368" },
          "ts": 1436375112257866
        }'

client.query(
  Get(
    Ref("classes/cars/104979509692858368"),
    Value(1436375112257866)));

client.query(
  q.Get(
    Ref("classes/cars/104979509692858368"),
    1436375112257866));

client.query(
  Get(Ref("classes/cars/104979509692858368"), 1436375112257866))

$client.query do
  get ref('classes/cars/104979509692858368'), 1436375112257866
end

client.Query(
  Get(Ref("classes/cars/104979509692858368"), 1436375112257866));

client.query(
  q.get(
    Ref("classes/cars/104979509692858368"),
    1436375112257866
  ))

client.Query(
    f.Get(
        f.Ref("classes/cars/104979509692858368"),
        1436375112257866,
    ),
)

client.query(
    Get(
        Ref("classes/cars/104979509692858368"),
        ts: 1436375112257866
    )
)

HTTP/1.1 404 Not Found
{
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

Change Many Events

When there’s bad data in your system, you may want to delete it from all history. This requires iterating through an instance’s events to clean every one of them.

In this case, suppose you don’t want license plate information in your system.

You can do it all in one query with a foreach over the event history. For each event, write a new event on top of it with the data you want. This means extracting just model and price out of the old data, meaning license gets erased.

Note that for delete events we do nothing, since there is no data associated with deletes.

(If you had multiple cars, you would need a nested foreach — one for each car, one for each event per car.)


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "foreach": {
            "lambda": "event",
            "expr": {
              "if": {
                "equals": [
                  { "select": "action", "from": { "var": "event" } },
                  "create"
                ]
              },
              "then": {
                "insert": { "select": "resource", "from": { "var": "event" } },
                "ts": { "select": "ts", "from": { "var": "event" } },
                "action": "create",
                "params": {
                  "let": {
                    "instance": {
                      "get": {
                        "select": "resource",
                        "from": { "var": "event" }
                      },
                      "ts": { "select": "ts", "from": { "var": "event" } }
                    }
                  },
                  "in": {
                    "object": {
                      "data": {
                        "object": {
                          "model": {
                            "select": [ "data", "model" ],
                            "from": { "var": "instance" }
                          },
                          "price": {
                            "select": [ "data", "price" ],
                            "from": { "var": "instance" }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "else": null
            }
          },
          "collection": {
            "paginate": { "@ref": "classes/cars/104979509692858368" },
            "events": true
          }
        }'

client.query(
  Foreach(
    Paginate(Ref("classes/cars/104979509692858368"))
      .events(Value(true)),
    Lambda(
      Value("event"),
      If(
        Equals(
          Select(Value("action"), Var("event")), Value("create")),
        Insert(
          Select(Value("resource"), Var("event")),
          Select(Value("ts"), Var("event")),
          Action.CREATE,
          Let(
            "instance", Get(
              Select(Value("resource"), Var("event")),
              Select(Value("ts"), Var("event")))
          ).in(
            Obj(
              "data", Obj(
                "model", Select(
                  Arr(Value("data"), Value("model")),
                  Var("instance")),
                "price", Select(
                  Arr(Value("data"), Value("price")),
                  Var("instance"))
              )
            )
          )),
        Null()))));

client.query(
  q.Foreach(
    q.Paginate(
      Ref("classes/cars/104979509692858368"),
      { events: true }),
    function(event) {
      return q.If(
        q.Equals(q.Select("action", event), "create"),
        q.Insert(
          q.Select("resource", event),
          q.Select("ts", event),
          "create",
          q.Let(
            {
              instance: q.Get(
                q.Select("resource", event),
                q.Select("ts", event))
            },
            {
              data: {
                model: q.Select(["data", "model"], q.Var("instance")),
                price: q.Select(["data", "price"], q.Var("instance"))
              }
            })),
        null);
    }));

client.query(
  Foreach(
    Paginate(
      Ref("classes/cars/104979509692858368"),
      events = true),
    Lambda { event =>
      If(
        Equals(Select("action", event), "create"),
        Insert(
          Select("resource", event),
          ts = Select("ts", event),
          action = "create",
          params = Let {
            val instance = Get(Select("resource", event), Select("ts", event))
            Obj(
              "data" -> Obj(
                "model" -> Select(Arr("data", "model"), instance),
                "price" -> Select(Arr("data", "price"), instance)
              )
            )
          }),
        Null())
    }))

$client.query do
  foreach paginate(ref('classes/cars/104979509692858368'),
           events: true) do |event|
    if_(equals(select('action', event), 'create'),
        insert(select('resource', event),
               select('ts', event),
               'create',
               let(instance: get(select('resource', event), select('ts', event))) do
                 data: {
                   model: select(['data', 'model'], instance),
                   price: select(['data', 'price'], instance)
                 }
               end),
        nil)
  end
end

client.Query(
  Foreach(
    Paginate(
      Ref("classes/cars/104979509692858368"),
      events: true),
    event => If(
      EqualsFn(Select("action", event), "create"),
      Insert(
        Select("resource", event),
        ts: Select("ts", event),
        action: "create",
        @params: Let(
          Obj(
            "instance", Get(Select("resource", event), Select("ts", event))
          ),
          Obj(
            "data", Obj(
              "model", Select(Arr("data", "model"), Var("instance")),
              "price", Select(Arr("data", "price"), Var("instance"))
            )
          ))),
      Null())));

client.query(
  q.foreach(
    lambda event: q.if_expr(
      q.equals(q.select("action", event), "create"),
      q.insert(
        q.select("resource", event),
        ts=q.select("ts", event),
        action="create",
        params=q.let(
          {
            "instance": q.get(
              q.select("resource", event),
              q.select("ts", event)
            )
          },
          {
            "data": {
              "model": q.select(["data", "model"], q.var("instance")),
              "price": q.select(["data", "price"], q.var("instance"))
            }
          }
        )
      ),
      None
    ),
    q.paginate(
      Ref("classes/cars/104979509692858368"),
      events=True
    )
  ))

client.Query(
    f.Foreach(
        f.Paginate(
            f.Ref("classes/cars/104979509692858368"),
            f.Events(true),
        ),
        f.Lambda(
            "event",
            f.If(
                f.Equals(
                    f.Select("action", f.Var("event")), "create",
                ),
                f.Insert(
                    f.Select("resource", f.Var("event")),
                    f.Select("ts", f.Var("event")),
                    f.ActionCreate,
                    f.Let(
                        f.Obj{
                            "instance": f.Get(
                                f.Select("resource", f.Var("event")),
                                f.Select("ts", f.Var("event")),
                            ),
                        },
                        f.Obj{
                            "data": f.Obj{
                                "model": f.Select(
                                    f.Arr{"data", "model"},
                                    f.Var("instance"),
                                ),
                                "price": f.Select(
                                    f.Arr{"data", "price"},
                                    f.Var("instance"),
                                ),
                            },
                        },
                    ),
                ),
                f.Null(),
            ),
        ),
    ),
)

client.query(
    Foreach(
        collection: Paginate(
            Ref("classes/cars/104979509692858368"),
            events: true
        ),
        in: { event in
            If(
                Equals(
                    Select(path: "action", from: event),
                    "create"
                ),
                then: Insert(
                    ref: Select(path: "resource", from: event),
                    ts: Select(path: "ts", from: event),
                    action: "create",
                    params: Let(
                        bindings: [
                        instance: Get(
                            Select(
                                path: "resource",
                                from: event
                            ),
                            ts: Select(path: "ts", from: event)
                        )
                        ],
                        in: Obj(
                            "data" => Obj(
                                "model" => Select(
                                    path: "data", "model",
                                    from: instance
                                ),
                                "price" => Select(
                                    path: "data", "price",
                                    from: instance
                                )
                            )
                        )
                    )
                ),
                else: nil
            )
        }
    )
)

HTTP/1.1 200 OK
{
  "resource": {
    "data": [
      {
        "ts": 1436375112199704,
        "action": "create",
        "resource": { "@ref": "classes/cars/104979509692858368" }
      },
      {
        "ts": 1436375112257866,
        "action": "delete",
        "resource": { "@ref": "classes/cars/104979509692858368" }
      },
      {
        "ts": 1436375112316028,
        "action": "create",
        "resource": { "@ref": "classes/cars/104979509692858368" }
      }
    ]
  }
}

=> {
  "data": [
    {
      "ts": 1436375112199704,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112257866,
      "action": "delete",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112199704,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112257866,
      "action": "delete",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112199704,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112257866,
      "action": "delete",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112199704,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112257866,
      "action": "delete",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112199704,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112257866,
      "action": "delete",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112199704,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112257866,
      "action": "delete",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112199704,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112257866,
      "action": "delete",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

=> {
  "data": [
    {
      "ts": 1436375112199704,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112257866,
      "action": "delete",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    },
    {
      "ts": 1436375112316028,
      "action": "create",
      "resource": { "@ref": "classes/cars/104979509692858368" }
    }
  ]
}

It’s now as if license plate information was never stored at any point in history.

Since you recently added a delete event to the history, fetching all event data requires checking for existence.


curl https://db.fauna.com/ \
    -u kqnPAi3Kj3ZgAAC0Hu51Ng2dtn0JcgP7Fb-Q_uzLGZE: \
    -d '{
          "map": {
            "lambda": "event",
            "expr": {
              "if": {
                "equals": [
                  { "select": "action", "from": { "var": "event" } },
                  "create"
                ]
              },
              "then": {
                "get": { "select": "resource", "from": { "var": "event" } },
                "ts": { "select": "ts", "from": { "var": "event" } }
              },
              "else": { "select": "ts", "from": { "var": "event" } }
            }
          },
          "collection": {
            "paginate": { "@ref": "classes/cars/104979509692858368" },
            "events": true
          }
        }'

client.query(
  Map(
    Paginate(Ref("classes/cars/104979509692858368"))
      .events(Value(true)),
    Lambda(
      Value("event"),
      If(
        Equals(
          Select(Value("action"), Var("event")), Value("create")),
        Get(
          Select(Value("resource"), Var("event")),
          Select(Value("ts"), Var("event"))),
        Select(Value("ts"), Var("event"))))));

client.query(
  q.Map(
    q.Paginate(
      Ref("classes/cars/104979509692858368"),
      { events: true }),
    function(event) {
      return q.If(
        q.Equals(q.Select("action", event), "create"),
        q.Get(
          q.Select("resource", event),
          q.Select("ts", event)),
        q.Select("ts", event));
    }));

client.query(
  Map(
    Paginate(
      Ref("classes/cars/104979509692858368"),
      events = true),
    Lambda { event =>
      If(
        Equals(Select("action", event), "create"),
        Get(Select("resource", event), Select("ts", event)),
        Select("ts", event))
    }))

$client.query do
  map paginate(ref('classes/cars/104979509692858368'),
           events: true) do |event|
    if_(equals(select('action', event), 'create'),
        get(select('resource', event), select('ts', event)),
        select('ts', event))
  end
end

client.Query(
  Map(
    Paginate(
      Ref("classes/cars/104979509692858368"),
      events: true),
    event => If(
      EqualsFn(Select("action", event), "create"),
      Get(Select("resource", event), Select("ts", event)),
      Select("ts", event))));

client.query(
  q.map_expr(
    lambda event: q.if_expr(
      q.equals(q.select("action", event), "create"),
      q.get(
        q.select("resource", event),
        q.select("ts", event)
      ),
      q.select("ts", event)
    ),
    q.paginate(
      Ref("classes/cars/104979509692858368"),
      events=True
    )
  ))

client.Query(
    f.Map(
        f.Paginate(
            f.Ref("classes/cars/104979509692858368"),
            f.Events(true),
        ),
        f.Lambda(
            "event",
            f.If(
                f.Equals(
                    f.Select("action", f.Var("event")), "create",
                ),
                f.Get(
                    f.Select("resource", f.Var("event")),
                    f.Select("ts", f.Var("event")),
                ),
                f.Select("ts", f.Var("event")),
            ),
        ),
    ),
)

client.query(
    Map(
        collection: Paginate(
            Ref("classes/cars/104979509692858368"),
            events: true
        ),
        to: { event in
            If(
                Equals(
                    Select(path: "action", from: event),
                    "create"
                ),
                then: Get(
                    Select(path: "resource", from: event),
                    ts: Select(path: "ts", from: event)
                ),
                else: Select(path: "ts", from: event)
            )
        }
    )
)

HTTP/1.1 200 OK
{
  "resource": {
    "data": [
      {
        "ref": { "@ref": "classes/cars/104979509692858368" },
        "class": { "@ref": "classes/cars" },
        "ts": 1436375112199704,
        "data": { "model": "mustang", "price": 30000 }
      },
      1436375112257866,
      {
        "ref": { "@ref": "classes/cars/104979509692858368" },
        "class": { "@ref": "classes/cars" },
        "ts": 1436375112316028,
        "data": { "model": "mustang", "price": 40000 }
      }
    ]
  }
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112199704,
      "data": { "model": "mustang", "price": 30000 }
    },
    1436375112257866,
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": { "model": "mustang", "price": 40000 }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112199704,
      "data": { "model": "mustang", "price": 30000 }
    },
    1436375112257866,
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": { "model": "mustang", "price": 40000 }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112199704,
      "data": { "model": "mustang", "price": 30000 }
    },
    1436375112257866,
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": { "model": "mustang", "price": 40000 }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112199704,
      "data": { "model": "mustang", "price": 30000 }
    },
    1436375112257866,
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": { "model": "mustang", "price": 40000 }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112199704,
      "data": { "model": "mustang", "price": 30000 }
    },
    1436375112257866,
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": { "model": "mustang", "price": 40000 }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112199704,
      "data": { "model": "mustang", "price": 30000 }
    },
    1436375112257866,
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": { "model": "mustang", "price": 40000 }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112199704,
      "data": { "model": "mustang", "price": 30000 }
    },
    1436375112257866,
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": { "model": "mustang", "price": 40000 }
    }
  ]
}

=> {
  "data": [
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112199704,
      "data": { "model": "mustang", "price": 30000 }
    },
    1436375112257866,
    {
      "ref": { "@ref": "classes/cars/104979509692858368" },
      "class": { "@ref": "classes/cars" },
      "ts": 1436375112316028,
      "data": { "model": "mustang", "price": 40000 }
    }
  ]
}

Conclusion

The event history of an instance is fully editable and changing the most recent event changes the current value of the instance. For more information, see the documentation for insert, remove, paginate, and history_days.