Creating multiple documents within single operation while using the ref of one

Hello!

I’m trying to create 2 documents within the same operation. The goal is to have one of them link to another via the ref. How can I do that?

Currently I’ve tried the following approach:

Map(
  [
    [
      "collection1",
      {
        coll1Prop1: "12345",
      }
    ],
    [
      "collection2",
      {
        collection1Ref: Call(Function("getDocRefByProp1"), "12345"),
        collection2Prop2: "randomProp"
      }
    ]
  ],
  Lambda(["collection", "data"],
    Create(
      Collection(Var("collection")),
      {
        data: Var("data")
      }
    )
  )
)

In this example I’m also using a Function getDocRefByProp1, which, as the name implies, returns the ref of document from collection1 by coll1Prop1 property.

I’m currently getting the following error:

Error: [
  {
    "position": [
      "collection",
      1,
      1,
      "object",
      "collection1Ref"
    ],
    "code": "call error",
    "description": "Calling the function resulted in an error.",
    "cause": [
      {
        "position": [
          "expr",
          "from"
        ],
        "code": "instance not found",
        "description": "Set not found."
      }
    ]
  }
]

Thank you in advance!

Hi Robert!

The error message shows that the problem occurs when calling the function. Can you share its current definition?

Hi Ewan, thanks for the prompt reply!

Here’s the function that’s being called:

Query(
  Lambda(
    "x",
    Select("ref", Get(Match(Index("docs_by_prop1"), Var("x"))))
  )
)

The index used is the following:

{
  name: "docs_by_prop1",
  unique: true,
  serialized: true,
  source: "collection1",
  terms: [
    {
      field: ["data", "coll1Prop1"]
    }
  ]
}

Am I right assuming that I’m trying to access a reference of a document which is not yet created within the transaction? If that’s the case, how can I add a reference to a document within the same transaction that it’s created?

When you create a document without a specified document ID, Fauna creates one for you:

> Create(Collection("foo"), { data: { bar: "xyzzy" }})
{
  ref: Ref(Collection("foo"), "332011350435824162"),
  ts: 1652889547700000,
  data: { bar: 'xyzzy' }
}

Notice that calling Create returns the document that was just created. So, you can do this:

> Select("ref", Create(Collection("foo"), { data: { bar: "xyzzy" }}))
Ref(Collection("foo"), "332011408194535970")

That’s most useful in a Let expression:

> Let(
  {
    newDocument:  Create(Collection("foo"), { data: { bar: "xyzzy" }}),
    newRef: Select("ref", Var("newDocument"))
  },
  {
    newDocument: Var("newDocument"),
    newRef: Var("newRef")
  }
)
{
  newDocument: {
    ref: Ref(Collection("foo"), "332011532657361442"),
    ts: 1652889721480000,
    data: { bar: 'xyzzy' }
  },
  newRef: Ref(Collection("foo"), "332011532657361442")
}

Another approach would be to call NewId to have a new document ID created:

> NewId()
'332011582404952610'

Then you can create a document with that document ID:

> Let(
  {
    newID: NewId(),
    newDocument: Create(
      Ref(Collection("foo"), Var("newID")),
      { data: { bar: "xyzzy" }}
    ),
    newRef: Select("ref", Var("newDocument"))
  },
  {
     newID: Var("newID"),
     newDocument: Var("newDocument"),
     newRef: Var("newRef")
  }
)
{
  newID: '332011779266708002',
  newDocument: {
    ref: Ref(Collection("foo"), "332011779266708002"),
    ts: 1652889956670000,
    data: { bar: 'xyzzy' }
  },
  newRef: Ref(Collection("foo"), "332011779266708002")
}

Using NewId might be useful if you need to work with that document ID before the document is actually created.

Awesome! I replaced my Map with Let and utilized the bindings. Thank you so much for helping me out :slight_smile:

2 Likes

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