PyDgraph sample and adding existing node as relationship

Hello

This is neither a bug or feature request, but a question.

What Dgraph client (and version) are you using?

(put “x” in the box to select)

  • Dgo
  • PyDgraph
  • Dgraph4J
  • Dgraph-js
  • Dgraph-js-http
  • Dgraph.NET

Version:

What version of Dgraph are you using?

Firstly, thank you for the Simple Example Project - this is extremely helpful and has allowed me to get started quickly.

I’m trying to add an association between a new entity and an existing entity. In the example, Two users (Alice, and her friend Bob) are created in a single mutation.

My question is, if Bob already existed, how would I associate the the Bob friendship to Alice?

Similarly, if Bob and John already existed, how would I associate a list of friends with Alice?

In my project I’ve tried to associate a list of UIDs, but that didnt work.

Thank you.

You get Bob’s UID(let’s say it is 0x3) and do something like

<0x3> <friend_of> _:Alice

Done.

In JSON

{
   "set": [
      {
         "uid": "0x3",
         "friend_of": [
            {
               "uid": "_:Alice"
            }
         ]
      }
   ]
}

Share what you did. I’ll help you.

Cheers.

Hi @MichelDiz

Thank you for your offer to help.

My relevant code is is:

        def set_responsibilities(self, responsibilities: [Responsibility], txn):
            logging.info(f'setting {len(responsibilities)} responsibilities')
            res = []
            for respond in responsibilities:
                logging.info(f'creating {respond.description.strip()}')
                r = [
                    {
                        'uid': f'_:',
                        'dgraph.type': 'Responsibility',
                        'name': f'{respond.description}',
                        'skills': [self._set_skills(respond, txn)]
                    }
                ]
                res = txn.mutate(set_obj=r)
                uid = res.uids[respond]
                logging.info(f'Created skill named {respond} with uid = {uid}')

                res.append(r)

            return res

        def _set_skills(self, responsibility: Responsibility, txn):
            logging.info(f'setting {len(responsibility.skills)} skills')
            skills = []
            for skill in responsibility.skills:
                s = {
                    'uid': f'_:{skill.name}',
                    'dgraph.type': 'Skill',
                    'name': f'{skill.name}'
                }

                res = txn.mutate(set_obj=s)
                uid = res.uids[skill.name]
                logging.info(f'Created skill named {skill.name} with uid = {uid}')

                skills.append(str(uid))

            return skills

The error I get is:

<_InactiveRpcError of RPC that terminated with:
	status = StatusCode.UNKNOWN
	details = "Got unsupported type for list: skills"
	debug_error_string = "{"created":"@1622968487.725468533","description":"Error received from peer ipv6:[::1]:9080","file":"src/core/lib/surface/call.cc","file_line":1066,"grpc_message":"Got unsupported type for list: skills","grpc_status":2}"
>

And my schema is:

        def set_schema(self, client: DgraphClient):
            schema = """
                name: string @index(exact) @upsert .
                email: string @index(exact) .
                linkedIn_url: string @index(exact) .
                github_url: string @index(exact) .
                dockerhub_url: string @index(exact) .
                friend: [uid] @reverse .
                employedBy: [uid] @reverse .
                skills: [uid]  .
                responsibilities_include: [uid] .
                age: int .
                married: bool .
                loc: geo .
                dob: datetime .
                <employedFrom>: datetime @index(month) .
                <employedUntil>: datetime @index(month) .
                <location>: string .
                type Company {
                    name
                    location
                }
                type <Position> {
                    employedFrom
                    employedUntil
                    employedBy
                    responsibilities_include
                }
                type Responsibility {
                    name
                    skills
                }
                type Skill {
                    name
                }
                type <Resume> {

                }
                type Person {
                    name
                    friend
                    age
                    married
                    loc
                    dob
                }
                """
            return client.alter(pydgraph.Operation(schema=schema))

My understanding, though I maybe wrong, is that I’m supposed to provide a list of UIDs, if I want to add an associating to multiple nodes.

Why this blank node is empty?

Are you sure that this will be transformed into a JSON array?

I’m not a python dev btw.

Are they all new skills? If not, you should use UID. You can also use Upsert Block to make your life easier.

Not sure, but based on this error, looks like your code is generating some other type of list instead of a JSON array.

Well this is mainly due to my lack of understanding. I thought this is value is set on creation.

Yes that is what the error would suggest. And the code in the original post was wrong - I was creating an error within an array. That is now corrected, however I’m still getting basically the same error - "Input for predicate "skills" of type uid is scalar. Edge: entity:32 attr:"\000\000\000\000\000\000\000\000skills" value:"0x1e" value_type:STRING "

The payload looks like:

[{'uid': '_:', 
'dgraph.type': 'Responsibility', 
'name': 'responsibility name', 
'skills': ['0x1a', '0x1b']}]

All skills are created prior. I’ll look to improve my code with upsert once I have these issues resolved. My main objective now is learning.

This should be like

[{'uid': '_:BlankNode1', 
'dgraph.type': 'Responsibility', 
'name': 'responsibility name', 
'skills': [{'uid': '0x1a'},{'uid': '0x1b'}]
}]

Not a list of UIDs, you should send a list of objects that holds the existing uids. That’s all.

Blank nodes are special identifiers, we use them to create new entities. And identifying them during a transaction. After the transaction, the identifiers are unrelated.

Thank you. This makes sense.