Get ID from Ref after creating a document using Java

Hi,

I’m trying to figure out how to get the ID of a document from the Ref block returned as a result of storing a new document in Fauna using Java. For example the following code create a new ‘customer’ document and stores it in the customer collection

Customer newCustomer = new Customer();
Value result = client.query(
                    Create(Collection("customers"), Obj("data", Value(newCustomer)))
                  ).get();

The result is a Value object and I can see in the data that is returned and the data structure in the Java objects defined by the result object that the ref and the id is there.

I can get a reference to a Value.RefV object by doing result.at("ref") which represents the ref block I could cast it to a Value.RefV and then use the getters on it to obtain the ID however this is an internal API and I shouldn’t use it but I can’t figure out how I am supposed to get it in Java.

Any help would be appreciated.

Hi @boxheed and welcome!

There should be no reason why you cannot use the getters provided to extract the ID in your java client. That is, the ID is intended to be a part of the Ref, and you can rely on using the getters in your production code. EDIT: This should be possible, I am checking what that way should be if not through casting to RefV, which is warned against in the Javadocs.

Other techniques using FQL

Another thing you can do is Select for the ID using FQL. I know some folks prefer to do it this way so it doesn’t have to be done client-side.

Here is some pure FQL that demonstrates getting the ID and even the Collection name if you desire.

Let(
  {
    thing_doc: Create(Collection("things"), { data: { value: true } }),
    thing_ref: Select("ref", Var("thing_doc")),
    thing_collection_name: Select(["ref", "collection", "id"], Var("thing_doc")),
    thing_id: Select(["ref", "id"], Var("thing_doc"))
  },
  {
    ref: Var("thing_ref"),
    collection_name: Var("thing_collection_name"),
    id: Var("thing_id"),
  }
)

// result
{
  ref: Ref(Collection("things"), "326390596491018306"),
  collection_name: "things",
  id: "326390596491018306"
}

similar to responses created by Fauna’s GraphQL API, you can stuff the Ref’s ID and ts field into the document and just return that, which is popular with some folks.

Let(
  {
    thing_doc: Create(Collection("things"), { data: { value: true } }),
    thing_id: Select(["ref", "id"], Var("thing_doc")),
    thing_ts: Select(["ts"], Var("thing_doc")),
    thing_data: Select(["data"], Var("thing_doc"))
  },
  Merge(Var("thing_data"), {
    _id: Var("thing_id"),
    _ts: Var("thing_ts")
  })
)

// result
{
  value: true,
  _id: "326414080735707202",
  _ts: 1647551575330000
}

I personally prefer passing around the whole Ref object, since you can pass it right back in to additional queries. Where your application needs the ID as a value, I like to extract out at the last moment, where the app state still stores the whole Ref. But what you want to do is up to you and what is best for your use case.

@ptpaterson that’s perfect it’s certainly the way I am merging in the ID when I am retrieving a document but didn’t know how to do the exact same operation when I create or update a doc. I’ve used your examples and updated my code to work in that way which works a treat.

I still think that there is something missing from the Java API with handling Ref objects in the client. Once you get hold of a Ref from a result (in Java this is a Value.RefV class but you don’t know that) you can’t do much with it unless you cast the Object to a Value.RefV however the docs for that state WARNING: Internal API. Must not be used in production code. but there is no other way to deal with it it seems unless I’m missing something?

Thank you for clarifying about the warnings in Javadocs to not use the Value types directly. Getting an ID from a Ref is a legitimate use case, so I am trying to figure out what the best way to do this with the Java driver, if not casting to Value.RefV.

1 Like

I’ve gotten clarification on the Javadocs warning.

It is not intended for clients to create instances of RefV directly. For that, there is the helper method Language.Ref.

However, I’ve confirmed that it is acceptable to cast query results to a RefV in order to handle them in your application. E.g. Result<RefV> ref = result.at("ref").to(Codec.REF);

I’ve filed an internal ticket to clarify the Javadocs.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.