3

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?

2 Answers2

3

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}
Cole Greer
  • 66
  • 3
1

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")
        }
    }