在Golang中处理查询结果

huangapple go评论63阅读模式
英文:

Handling query results in Golang

问题

考虑以下在Go中执行Gremlin查询并解释或解析结果的方法。

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
}

显然,我可以添加辅助方法来简化查询处理代码。但无论如何,查询处理代码都必须处理多层的map[any]any和任意值。

我是否遗漏了在驱动程序Result对象中使此过程更容易的一些方法?

英文:

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?

答案1

得分: 3

Go GLV没有内置的工具来帮助遍历地图。如果您不需要完整的地图,我建议不使用ElementMap()步骤。由于您似乎只需要“entity”和“component”的id以及组件值,您可以通过使用仅选择这些项的遍历来简化结果,而不是使用完整的元素地图。以下是在gremlin控制台上使用示例数据集执行类似操作的示例:

gremlin> g.V().repeat(__.as("a").inE().outV().simplePath()).emit().until(__.outE().count().is(0)).filter(__.hasLabel("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"}
英文:

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}

答案2

得分: 1

这样做可以清理一些东西,但显然不安全,可能会导致恐慌。

	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("不是一个映射\n")
		}
	}
英文:

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

huangapple
  • 本文由 发表于 2023年2月17日 05:07:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75477937.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定