Skip to content

Commit

Permalink
feat: add delete all KG nodes example
Browse files Browse the repository at this point in the history
Closing ENG-1939
  • Loading branch information
cowan-macady committed Oct 26, 2023
1 parent 5ee2989 commit 10df5cb
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 3 deletions.
55 changes: 55 additions & 0 deletions examples/knowledge/cmd/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) 2023 IndyKite
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"context"
"fmt"

"github.com/spf13/cobra"
)

// deleteCmd represents the command for deleting the nodes in a KG
var deleteCmd = &cobra.Command{
Use: "delete",
Short: "Delete nodes in the IndyKite Knowledge API",
Long: `Delete nodes in the IndyKite Knowledge API`,
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, args []string) {
records, err := client.NodesRecordsWithTypeNode(context.Background(), "DigitalTwin")
if err != nil {
fmt.Println(err.Error())
}
records2, err := client.NodesRecordsWithTypeNode(context.Background(), "Resource")
if err != nil {
fmt.Println(err.Error())
}
if len(records2) > 0 {
records = append(records, records2...)
}
fmt.Println(records)
resp, err := clientIngest.StreamRecords(records)
if err != nil {
fmt.Println(err.Error())
}
for _, response := range resp {
fmt.Println(jsonp.Format(response))
}
},
}

func init() {
rootCmd.AddCommand(deleteCmd)
}
18 changes: 15 additions & 3 deletions examples/knowledge/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ import (

"github.com/indykite/indykite-sdk-go/grpc"
apicfg "github.com/indykite/indykite-sdk-go/grpc/config"
"github.com/indykite/indykite-sdk-go/ingest"
"github.com/indykite/indykite-sdk-go/knowledge"
)

var (
cfgFile string
client *knowledge.Client
jsonp = protojson.MarshalOptions{
cfgFile string
client *knowledge.Client
clientIngest *ingest.Client
jsonp = protojson.MarshalOptions{
Multiline: true,
EmitUnpopulated: true,
}
Expand All @@ -58,6 +60,9 @@ func Execute() {
if client != nil {
_ = client.Close()
}
if clientIngest != nil {
_ = clientIngest.Close()
}
}()
}

Expand Down Expand Up @@ -100,6 +105,13 @@ func initConfig() {
if err != nil {
er(fmt.Sprintf("failed to create IndyKite Identity Knowledge Client: %v", err))
}
clientIngest, err = ingest.NewClient(context.Background(),
grpc.WithCredentialsLoader(apicfg.DefaultEnvironmentLoader),
grpc.WithRetryOptions(retry.Disable()),
)
if err != nil {
er(fmt.Sprintf("failed to create IndyKite Ingest Client: %v", err))
}
}

func er(msg any) {
Expand Down
55 changes: 55 additions & 0 deletions knowledge/knowledge_read.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@ package knowledge

import (
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"strings"

"golang.org/x/text/cases"
"golang.org/x/text/language"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"

"github.com/indykite/indykite-sdk-go/errors"
ingestpb "github.com/indykite/indykite-sdk-go/gen/indykite/ingest/v1beta2"
knowledgepb "github.com/indykite/indykite-sdk-go/gen/indykite/knowledge/v1beta1"
objects "github.com/indykite/indykite-sdk-go/gen/indykite/objects/v1beta1"
)
Expand Down Expand Up @@ -255,6 +260,56 @@ func parseMultipleNodesFromPaths(paths []*knowledgepb.Path) ([]*knowledgepb.Node
return nodes, nil
}

func GenerateRandomString(length int) string {
b := make([]byte, length)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
return base64.StdEncoding.EncodeToString(b)
}

// NodesRecordsWithTypeNode is a helper function that get all nodes of specific type either DigitalTwin
// or Resource and transform them into records.
func (c *Client) NodesRecordsWithTypeNode(
ctx context.Context,
nodeType string,
opts ...grpc.CallOption,
) ([]*ingestpb.Record, error) {
ctx = insertMetadata(ctx, c.xMetadata)
path := fmt.Sprintf("(:%s)", nodeType)
resp, err := c.client.IdentityKnowledge(ctx, &knowledgepb.IdentityKnowledgeRequest{
Path: path,
Operation: knowledgepb.Operation_OPERATION_READ,
}, opts...)
if err != nil {
return nil, err
}
nodes, err := parseMultipleNodesFromPaths(resp.GetPaths())
if err != nil {
return nil, err
}
records := []*ingestpb.Record{}
for _, node := range nodes {
caser := cases.Title(language.English)
record := &ingestpb.Record{
Id: GenerateRandomString(12),
Operation: &ingestpb.Record_Delete{
Delete: &ingestpb.DeleteData{
Data: &ingestpb.DeleteData_Node{
Node: &ingestpb.NodeMatch{
ExternalId: node.ExternalId,
Type: caser.String(node.Type),
},
},
},
}, // lint:file-ignore U1000 Ignore report
}
records = append(records, record)
}
return records, nil
}

// Identifier is the combination of ExternalID and Type
// which uniquely identifies a node in the Identity Knowledge Graph.
type Identifier struct {
Expand Down

0 comments on commit 10df5cb

Please sign in to comment.