Syntax for creating & upserting nested models

Hi we are looking for examples on creating & upserting data with graph relationships.

In the example of a Post with Comments,

We are aware that the child (Comment) should have fields with @documentReference and @relationDocument directives to the parent (Post) .The parent should also have a field with @relationFrom directive referencing the ID field of Child. Supported directives | ComposeDB on Ceramic

We know how to compile and deploy such models, but are keen to see a working example of creating instances of Parent and Child.

Is it as simple as first creating Parent class to get a Parent instance id, then using that with the Parent model deployed address/stream/id to have the parameters for the @documentReference and @relationDocument fields when creating a child?

Also is it possible to do a nested mutation, where I can create the Parent and initialize or upsert Children, completely replace existing Children? Performing mutations | ComposeDB on Ceramic Hints at this

Once again looking for working examples. Thanks!

Yes, that sounds right.

I’m not quite sure I understand your question about upserting Models, but please note that Models are immutable and cannot be updated after they are published.

@paul if you have any bandwidth can you take a look + share an example that we can include in the docs?

Not sure what you mean by “Parent class” and “instance id”, but if you want to add a Comment relation to a Post for example, you simply need to create a Comment document setting the post ID to reference in the specified field.

No, that’s not possible as each document creation or update requires a unique transaction.

To see the possible queries and mutations that can be performed over your composite, I’d suggest running GraphiQL as documented in https://composedb.js.org/docs/preview/interact-with-data

Hi thanks for the comments, I am understanding this better but still have few things to figure out,

My models look like the following:

Proposal:

type NounsProposalVote @loadModel(id: "kjzl6hvfrbw6c6dmc8dbqgj4wvjqlfh1cha44nmwqqukde9mh5wswtsk6vi3gf2") {
  id: ID!
}

type NounsProposal @createModel(accountRelation: LIST, description: "On-chain proposals and their voting stats") {
  abstainVotes: Int! @int(min: 0)
  againstVotes: Int! @int(min: 0)
  ...
  daoName: String! @string(maxLength:1000)
  votes: [NounsProposalVote] @relationFrom(mode: "NounsProposalVote", property: "id")
}

Proposal vote:

type NounsProposal @loadModel(id: "kjzl6hvfrbw6c8ycbb32z6pg2xbk2a2g7yy098dxklop09utbdhhrbea3t805z2") {
  id: ID!
}

type NounsProposalVote @createModel(accountRelation: LIST, description: "On-chain proposal votes") {
  proposal_stream_id: StreamID! @documentReference(model: "NounsProposal")
  nouns_proposal: NounsProposal! @relationDocument(property: "proposal_stream_id")

  eth_address: String! @string(maxLength:256)
  ...
  vote_id: String! @string(maxLength:512)
  votes: Int! @int(min: 0)
}

Wondering how to get the right value for @loadModel directive, it seems I need to deploy the model to get that loadModel parameter, so it feels like circular dependency.

I am able to create simple models (no nested relationship) with graphql mutation, but still have to figure out the syntax to create a ProposalVote (how to pass the associated Proposal id in create mutation)

Would appreciate pointer if this is the right direction for passing a Proposal id (proposal_stream_id field)

const create_vote_query = `
    mutation CreateNounsProposalVote($vote: CreateNounsProposalVoteInput!) {
      createNounsProposalVote(input: $vote) {
          document {
            // Is this the right field & location in this context?
            proposal_stream_id     // Parent proposal id
            eth_address
            vote_id
            ...
            votes
          }
        }
    }`

    const create_vote_variables = {
      "vote": {
        "content": vote
      }
    }

Thanks!

Hi, your example seems pretty similar to what is described in the docs in Relations | ComposeDB on Ceramic
Essentially the flow is to create 3 different composites as follows:

  1. Create your Proposal model with only its content fields (no views)
  2. Create your ProposalVote model with a @documentReference directive (see Supported directives | ComposeDB on Ceramic) pointing to the Proposal model created in step 1.
  3. Load your Proposal model and add a view with the @relationFrom directive (see Supported directives | ComposeDB on Ceramic) pointing to the ProposalVote model created in step 2.

Regarding your question about creating ProposalVote documents, yes you simply need to provide the ID of the Proposal document in the field set as holding the relation with the @documentReference directive.

Updating the docs link: Relations | ComposeDB on Ceramic

We were able to get it to work with the examples, thanks @paul!

1 Like

Great to know, thanks!