"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > How Can You Store Workflows with Diverse Node Types in MongoDB using Mgo (Go)?

How Can You Store Workflows with Diverse Node Types in MongoDB using Mgo (Go)?

Published on 2024-11-09
Browse:839

How Can You Store Workflows with Diverse Node Types in MongoDB using Mgo (Go)?

Interface as Model in Mgo (Go): Resolving the Assignability Error

When dealing with workflows comprising nodes of varying types, it may be tempting to leverage Golang interfaces to encapsulate their diverse behaviors. However, storing such workflows in MongoDB poses a unique challenge.

The Assignability Issue

The error encountered during the Find operation stems from the incompatibility between the decoded document and the Node interface. Mgo lacks the type information necessary to determine the specific type of each embedded node. This results in an assignment mismatch.

Alternative Approach: Embedding with Type Information

To overcome this hurdle, consider encapsulating the type information within the embedded nodes. Define a new struct, NodeWithType, which consists of the Node interface and a Type field representing the specific type.

type NodeWithType struct {
   Node Node `bson:"-"`
   Type string
}

Custom BSON Unmarshaling

To bridge the gap between the decoded document and the Go struct, implement the SetBSON function for NodeWithType. This function will decode the Type field, create an instance of the corresponding type, and delegate the unmarshaling to it.

func (nt *NodeWithType) SetBSON(r bson.Raw) error {
   // Decode Type field
   var typeName string
   err := bson.Unmarshal(r["Type"], &typeName)
   if err != nil {
      return err
   }

   // Create an instance of the correct type based on Type field
   var node Node
   switch typeName {
   case "EmailNode":
      node = &EmailNode{}
   case "TwitterNode":
      node = &TwitterNode{}
   }

   // Unmarshal the remaining fields into the created instance
   if err = node.SetBSON(r[typeName]); err != nil {
      return err
   }

   // Assign the created instance to the Node field
   nt.Node = node

   return nil
}

In the Workflow struct, replace the Node slice with a slice of NodeWithType.

type Workflow struct {
   CreatedAt time.Time
   StartedAt time.Time
   CreatedBy string
   Nodes []NodeWithType
}

With this approach, Mgo can now successfully find and unmarshal workflows with embedded nodes of different types.

Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3