Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling query results in Golang

Consider the following method which executes a gremlin query in Go and then interprets or parses the results.

func (n NeptuneGremlinGraph) Query(assetID string, version string, entityID string) ([]hz.Component, error) {
    defer utils.TimeTracker(time.Now(), fmt.Sprintf("Graph Query"))
    g := gremlin.Traversal_().WithRemote(n.connection)
    anonT := gremlin.T__
    results, err := g.V(makeId(assetID, version, entityID)).
        Repeat(anonT.As("a").InE().OutV().SimplePath()).
        Emit().Until(anonT.OutE().Count().Is(0)).
        Filter(anonT.HasLabel("Component")).
        Project("entity", "component").
        By(anonT.Select("a").ElementMap()).
        By(anonT.ElementMap()).
        ToList()
    if err != nil {
        return nil, err
    }
    cnt := 0
    for _, r := range results {
        var entityID, componentID, value string
        if m, ok := r.Data.(map[any]any); ok {
            if entity, ok := m["entity"]; ok {
                if entity, ok := entity.(map[any]any); ok {
                    if id, ok := entity["id"]; ok {
                        if id, ok := id.(string); ok {
                            _, _, entityID = splitId(id)
                        }
                    }
                }
            }
            if component, ok := m["component"]; ok {
                if component, ok := component.(map[any]any); ok {
                    if id, ok := component["component_id"]; ok {
                        if id, ok := id.(string); ok {
                            componentID = id
                        }
                    }
                    if v, ok := component["value"]; ok {
                        if v, ok := v.(string); ok {
                            value = v
                        }
                    }
                }
            }
            log.Printf("%s, %s, %s\n", entityID, componentID, value)
        } else {
            log.Printf("not a map\n")
        }
    }
    log.Printf("path cnt = %d\n", cnt)
    return nil, nil
}

Obviously I could add helper methods to clean up the query processing code. But either way the query processing code has to deal with multiple layers of map[any]any and any values.

Am I missing some methods in the driver Result object that make this easier?

like image 264
Michael Burbidge Avatar asked Jan 26 '26 03:01

Michael Burbidge


2 Answers

The Go GLV does not have any built in tools to assist in traversing maps. I would suggest not using the ElementMap() step if you do not need the full map. Since it appears that the only data you are looking for is the id of both “entity” and “component” as well as the component value, you could simplify your result by using a traversal which only selects these items, instead of the full element maps. The following is an example from gremlin console doing something similar to this using a sample dataset:

gremlin> g.V().repeat(__.as("a").inE().outV().simplePath()).emit().until(__.outE().count().is(0)).filter(__.hasLab
el("person")).project("entityID", "personID", "personValue").by(__.select("a").id()).by(__.id()).by(__.values()).toList()
==>{entityID=2, personID=1, personValue=marko}
==>{entityID=3, personID=1, personValue=marko}
==>{entityID=3, personID=4, personValue=josh}
==>{entityID=3, personID=6, personValue=peter}
==>{entityID=4, personID=1, personValue=marko}
==>{entityID=4, personID=1, personValue=marko}
==>{entityID=5, personID=4, personValue=josh}
==>{entityID=4, personID=1, personValue=marko}
like image 185
Cole Greer Avatar answered Jan 28 '26 21:01

Cole Greer


This cleans things up, but is obviously not safe, and could lead to panics.

    for _, r := range results {
        var entityID, componentID, value string
        if m, ok := r.Data.(map[any]any); ok {
            _, _, entityID = splitId(m["entity"].(map[any]any)["id"].(string))
            componentID = m["component"].(map[any]any)["component_id"].(string)
            value = m["component"].(map[any]any)["value"].(string)
            components = append(components, hz.Component{
                EntityID:    entityID,
                ComponentID: componentID,
                Value:       value,
            })
        } else {
            log.Printf("not a map\n")
        }
    }
like image 29
Michael Burbidge Avatar answered Jan 28 '26 21:01

Michael Burbidge