Is there a way to upsert all outgoing nodes in one mutation

mutation

(Cbwleft) #1

I kown how to upsert a single node, but some type of node can’t exist independently, they must be a outcoming node from a container type.

Here is my scenario, I wan’t to synchronize metadata from a relational database periodically. my type definition looks like this

type Table {
    name string
    description string
    columns [Column]
    qualifiedName string
}

type Column {
    name string
    description string
    dataType string
}

After I get the compelte instance of ‘Table’ with its ‘columns’ in my java code, I want to upsert it in dgraph. My mutation looks like this

upsert {
   query {
     var(func: eq(qualifiedName, "db.table")) {
       id as uid
     }
   }
   mutation {
       set {
        uid(id) <name> "table" .
        uid(id) <description> "update description" .
        uid(id) <qualifiedName> "db.table" .
        uid(id) <columns> "_:column" .
       _:column <name> "id" .
        _:column <description> "update description" .
        _:column <dataType> "long" .
       }
   }
 }

If the node ‘Table’ doesn’t exist, insert it won’t be a problem.
If the node ‘Table’ already exist, update it’s attributes won’t be a problem. but the mutation will make duplicate node of ‘Column’.

In my scenario, the column may be added, deleted or updated, Is there a way to upsert all these outcoming nodes other than check these nodes one by one?


(Michel Conrado) #2

For this you can use https://docs.dgraph.io/mutations/#conditional-upsert

e.g:

query {
     var(func: eq(qualifiedName, "db.table")) {
       id as uid
     }
     var(func: eq(name, "id?")) {
       idcolumn as uid
     }
   }

You can also combine multiple query blocks to define whether mutate it or not. Soon we gonna support multiple mutations, so you could do a kind of “if/else” logic.


(Cbwleft) #3

Thanks for your reply, but I still don’t understand how to find deleted node by a condition.

For example, I have a table with two columns:

query {
     var(func: eq(qualifiedName, "db.table")) {
       id as aid
       col1 as column @filter(eq(name, "column1"))
       col2 as column @filter(eq(name, "column2"))
       colAll as column
     }
   }

then I can use these query variable col1, col2 in my mutation. how can I kown which uid in colAll not in collection of col1 and col2, and then delete them?


(Michel Conrado) #4

What exactly you mean by “deleted node”? If you have deleted nodes, it will be empty nodes. And if those deleted nodes are connected with actual nodes. You gonna have dangling outgoing edges. Pointing to empty nodes.

Please, give me a sample of your data. And desired results. So I can follow your reasoning.

Maybe like this:

query {
     var(func: eq(qualifiedName, "db.table")) {
       id as uid
       col1 as column @filter(eq(name, "column1"))
       col2 as column @filter(eq(name, "column2"))
       colAll as column
     }

     var(func: uid(colAll)) @filter(Not uid(col1,col2)) {
       useThis as uid
     }
        
   }

(Cbwleft) #5

My dataset looks like this:

{
	"name": "table",
	"column": [{
		"name": "col1",
		"dataType": "string"
	}, {
		"name": "col2",
		"dataType": "string"
	}]
}

and after I delete col2:

{
	"name": "table",
	"column": [{
		"name": "col1",
		"dataType": "string"
	}]
}

That may work,I will try to use this in delete block,thanks again。