2

The following is a complex family members relationships represented with nodes and edges.

  1. The member represented as person node
  2. The marriage node represent the marriage between two person nodes
  3. son_of and daughter_of connect a person to a marriage node.
  4. root_person is first generation
  5. john and Brenda are second generation
  6. mark is third generation
  7. mary is fourth generation
  8. john has an ex-wife and wife
  9. mark and his ex-wife mark_ex_wife are cousins. This is because mark's father and mark_ex_wife's mother are siblings.

My requirement is to get all the nodes in hierarchical tree format. Starting with the root_person, his son john and his wife and the daughter brenda' and her husband should be returned. Then the next generation and so on...

Please answer whether my requirement is achievable with this model, or modify this model to get all the nodes. The JSON with key and value returned by the CosmosDB data explorer is the start. I can then parse the JSON returned by the query to create a hierarchical tree of parents and children in a custom format which is more easy to understand and print out.

g.V().drop()
g.E().drop()
g.addV('person').property(id, 'root_person').property('name', 'Root Person').property('title', 'male')
g.addV('person').property(id, 'root_person_wife').property('name', 'root_person_wife').property('title', 'female')
g.addV('person').property(id, 'john').property('name', 'john').property('title', 'male')
g.addV('person').property(id, 'john_wife').property('name', 'john_wife').property('title', 'female')
g.addV('person').property(id, 'john_ex_wife').property('name', 'john_ex_wife').property('title', 'female')
g.addV('person').property(id, 'brenda').property('name', 'brenda').property('title', 'female')
g.addV('person').property(id, 'brenda_husband').property('name', 'brenda_husband').property('title', 'male')
g.addV('person').property(id, 'mark').property('name', 'mark').property('title', 'male')
g.addV('person').property(id, 'mark_ex_wife').property('name', 'mark_ex_wife').property('title', 'female')
g.addV('person').property(id, 'mark_wife').property('name', 'mark_wife').property('title', 'female')
g.addV('person').property(id, 'mary').property('name', 'mary').property('title', 'female')
g.addV('person').property(id, 'mary_husband').property('name', 'mary Husband').property('title', 'male')
g.addV('marriage').property(id, 'root_person-root_person_wife').property('marriage_name', 'root_person-root_person_wife')
g.addV('marriage').property(id, 'john-john_wife').property('marriage_name', 'john-john_wife')
g.addV('marriage').property(id, 'john-john_ex_wife').property('marriage_name', 'john-john_ex_wife')
g.addV('marriage').property(id, 'brenda-brenda_husband').property('marriage_name', 'brenda-brenda_husband')
g.addV('marriage').property(id, 'mark-mark_ex_wife').property('marriage_name', 'mark-mark_ex_wife')
g.addV('marriage').property(id, 'mark-mark_wife').property('marriage_name', 'mark-mark_wife')
g.addV('marriage').property(id, 'mary-mary_husband').property('marriage_name', 'mary-mary_husband')

g.V('root_person').addE('married_in').to(g.V('root_person-root_person_wife'))
g.V('root_person_wife').addE('married_in').to(g.V('root_person-root_person_wife'))
g.V('john').addE('married_in').to(g.V('john-john_wife'))
g.V('john_wife').addE('married_in').to(g.V('john-john_wife'))
g.V('john').addE('married_in').to(g.V('john-john_ex_wife'))
g.V('john_ex_wife').addE('married_in').to(g.V('john-john_ex_wife'))
g.V('brenda').addE('married_in').to(g.V('brenda-brenda_husband'))
g.V('brenda_husband').addE('married_in').to(g.V('brenda-brenda_husband'))
g.V('mark').addE('married_in').to(g.V('mark_#mark_wife'))
g.V('mark_wife').addE('married_in').to(g.V('mark-mark_wife'))
g.V('mark').addE('married_in').to(g.V('mark-mark_ex_wife'))
g.V('mark_ex_wife').addE('married_in').to(g.V('mark-mark_ex_wife'))
g.V('mary').addE('married_in').to(g.V('mary-mary_husband'))
g.V('mary_husband').addE('married_in').to(g.V('mary-mary_husband'))

g.V('john').addE('son_of').to(g.V('root_person-root_person_wife')).property('son_of', 'john--root_person-root_person_wife')
g.V('brenda').addE('daughter_of').to(g.V('root_person-root_person_wife')).property('daugter_of', 'brenda--root_person-root_person_wife')
g.V('mark').addE('son_of').to(g.V('john-john_wife')).property('son_of', 'mark--john-john_wife')
g.V('mark_ex_wife').addE('daughter_of').to(g.V('brenda-brenda_husband')).property('daugter_of', 'mark_ex_wife--brenda-brenda_husband')
g.V('mary').addE('daughter_of').to(g.V('mark-mark_wife')).property('daugter_of', 'mary--mark-mark_wife') }

UPDATE:

I tried the following query in my cosmosdb query explorer but it does not bring-in all the nodes.

g.V('root_person').repeat(out('married_in')).emit().repeat(__.in('son_of', 'daughter_of')).emit().tree()

The query produced the following json. You will notice that it stopped at the second generation.

[
  {
    "root_person": {
      "key": {
        "id": "root_person",
        "label": "person",
        "type": "vertex",
        "properties": {
          "name": [
            {
              "id": "f1e8327e-add4-454b-bbb2-6f076a29ea49",
              "value": "Root Person"
            }
          ],
          "title": [
            {
              "id": "42fc9c2b-b613-4011-9a0a-183d907a96ac",
              "value": "male"
            }
          ]
        }
      },
      "value": {
        "root_person-root_person_wife": {
          "key": {
            "id": "root_person-root_person_wife",
            "label": "marriage",
            "type": "vertex",
            "properties": {
              "marriage_name": [
                {
                  "id": "30f428a9-e657-4284-b59a-b836d9f04887",
                  "value": "root_person-root_person_wife"
                }
              ]
            }
          },
          "value": {
            "john": {
              "key": {
                "id": "john",
                "label": "person",
                "type": "vertex",
                "properties": {
                  "name": [
                    {
                      "id": "64e4653d-6298-479d-ba0f-eb3a9ede2383",
                      "value": "john"
                    }
                  ],
                  "title": [
                    {
                      "id": "b99dacb3-e38d-4da8-b087-42860d2b28c0",
                      "value": "male"
                    }
                  ]
                }
              },
              "value": {}
            },
            "brenda": {
              "key": {
                "id": "brenda",
                "label": "person",
                "type": "vertex",
                "properties": {
                  "name": [
                    {
                      "id": "1d88e8a5-7340-4b6d-a2b9-8b3c325e7bf6",
                      "value": "brenda"
                    }
                  ],
                  "title": [
                    {
                      "id": "9b856caa-0b84-413c-8229-8e2c1e0cb0d3",
                      "value": "female"
                    }
                  ]
                }
              },
              "value": {}
            }
          }
        }
      }
    }
  }
]
wonderful world
  • 10,969
  • 20
  • 97
  • 194
  • 1
    Please fix your script that creates the sample graph. If you want to access a vertex via `V('mark')`, you have to set its `id` to `mark`, no just a property named `id` (e.g. `addV('person').property(id, 'mark')`). Next, make sure that things are consistent. In your edge creation statements, you're referring to elements that were never created. Fixing those issues will probably fix the whole problem. – Daniel Kuppitz Sep 20 '19 at 13:40
  • I fixed the script and updated the original post. There was a ```marriage``` vertex missing. I changed the ```id``` also. But that did not make any difference. The query stops at the second generation as you see in the result. I don't know how can I traverse each and every node in a bredth-first style and generate all the nodes. – wonderful world Sep 21 '19 at 02:25

1 Answers1

2

A tree will represent the vertices in the same hierarchy as they are stored in the graph. Thus, spouses will not appear at the same level in a tree. I might be wrong, but I think what you want is a list of people in each generation..?

gremlin> g.V("root_person").
           union(identity(),
                 out("married_in").in("married_in")).dedup().
           aggregate("x").
           group("m").
             by(constant(-1)).
             by(id).
           repeat(out("married_in").
                  union(__.in("married_in"),
                        __.in("daughter_of","son_of").
                           union(identity(), 
                                 out("married_in").in("married_in"))).dedup().
                  where(without("x")).
                  aggregate("x").
                  group("m").
                    by(loops()).
                    by(id)).
           cap("m").unfold().
           order(local).
             by(keys).
           select(values)
==>[root_person,root_person_wife]
==>[brenda,brenda_husband,john,john_wife,john_ex_wife]
==>[mark_ex_wife,mark,mark_wife]
==>[mary,mary_husband]
Daniel Kuppitz
  • 10,846
  • 1
  • 25
  • 34
  • I'm struggling to understand how the above query will be executed. I'm using the *CosmosDB DBExplorer* and run the queries directly in the browser. The DBExplorer supports only a few steps as described [here](https://learn.microsoft.com/en-us/azure/cosmos-db/gremlin-support). I had to use the query that you suggested in a different [stackoverflow question](https://stackoverflow.com/questions/56703768/how-to-generate-a-custom-json-output-from-a-cosmosdb-graph-using-gremlin) to get all the nodes and vertexes. – wonderful world Oct 04 '19 at 01:00
  • Does Neo4J cypher queries follow the functional language approach like Gremlin language? There are so many resources out there to learn Neo4J, so thinking about doing this query of DAG to generate tree in Neo4J. What do you recommend? – wonderful world Oct 04 '19 at 01:05
  • 1
    Cypher is purely declarative, but you can use Gremlin over Neo4J. – Daniel Kuppitz Oct 07 '19 at 14:52