Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gremlin python - add multiple but an unknown number of properties to a vertex

Tags:

I want to add more than one property to a vertex, but from the outset do not explicitly know what those properties might be. For example, say for one person to be added as vertex to the graph, we have the following property dictionary:

Person 1

{
    "id": 1,
    "first_name": "bob",
    "age": 25,
    "height": 177
}

Maybe for another vertex to be added, a person has the following properties:

Person 2

{
    "id": 2,
    "first_name": "joe",
    "surname": "bloggs",
    "occupation": "lawyer",
    "birthday": "12 September"
}

Is there a way to add both people into the graph without explicitly hardcoding the property keys and values into the Gremlin property function?

This link provides an answer in the right direction. Further useful information can be found here. The following line mirrors the proposed solution, executes as expected, and adds a new vertex into the graph. Great.

g.addV("person").property("id", 1, "first_name", "bob", "age", 25, "height", 177).next()

BUT, it only seeks to work if the inputs are hardcoded. I've transformed the property dictionaries to a tuple of values in the form (k1, v1, k2, v2, ..., kn, vn), but I'm unable to programmatically pass in the values. E.g.

tup_vals = ("id", 1, "first_name", "bob", "age", 25, "height", 177)

But for whatever reason, I cannot call:

g.addV("person").property(*tup_vals).next()

The above line doesn't throw an Exception, it just doesn't execute as expected (i.e. the properties are not being passed in)

Does anyone have any insight on how to pass these property dictionaries into the Gremlin property function in a computational way?


Update: naive/inefficient solution

A solution is provided below, but it's a bad solution because each iteration it queries the gremlin server. Ideally I want to add all properties at the same time. And only really works as expected if the id is unique.

g.addV("person").property('id', id).next()

for k,v in property_dictionary[id].items():
     g.V().has('id', id).property(k, v).iterate()

Answer

Thanks to Daniel for the answer. I've adapted his answer (below) to conform with the gremlin_python package.

Important note from this answer: keys and values in the given context should import from the Column enum - in the source code here.

from gremlin_python.process.graph_traversal import __
from gremlin_python.process.traversal import Column

persons = [{"id":1,"first_name":"bob","age":25,"height": 177}, {"id":2,"first_name":"joe","surname":"bloggs","occupation":"lawyer","birthday":"12 September"}]    

g.inject(persons).unfold().as_('entity').\
    addV('entity').as_('v').\
        sideEffect(__.select('entity').unfold().as_('kv').select('v').\
                   property(__.select('kv').by(Column.keys),
                            __.select('kv').by(Column.values)
                            )
                  ).iterate()
like image 891
Ian Avatar asked Jun 14 '19 17:06

Ian


1 Answers

You can inject your maps/dictionaries into the traversal, create a vertex for each dictionary and then go through all dictionary/map-entries and set them as properties. In Gremlin that looks like this:

g.inject(persons).unfold().as('person').
  addV('person').as('v').
  sideEffect(select('person').unfold().as('kv').
             select('v').
               property(select('kv').by(keys), select('kv').by(values))).
  iterate()

Example:

gremlin> persons = [["id":1,"first_name":"bob","age":25,"height": 177]
......1>           ,["id":2,"first_name":"joe","surname":"bloggs",
                       "occupation":"lawyer","birthday":"12 September"]]
==>[id:1,first_name:bob,age:25,height:177]
==>[id:2,first_name:joe,surname:bloggs,occupation:lawyer,birthday:12 September]

gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.inject(persons).unfold().as('person').
......1>   addV('person').as('v').
......2>   sideEffect(select('person').unfold().as('kv').
......3>              select('v').
......4>                property(select('kv').by(keys), select('kv').by(values))).
......5>    valueMap()
==>[id:[1],first_name:[bob],age:[25],height:[177]]
==>[birthday:[12 September],occupation:[lawyer],surname:[bloggs],id:[2],first_name:[joe]]
like image 109
Daniel Kuppitz Avatar answered Oct 31 '22 13:10

Daniel Kuppitz