The blogpost on recommendation engines does a good job of explaining variable propagation. It is best understood by drawing a graph and calculating the value of a variable at different levels
The blogpost mentions:
In short, the value that a node receives is equal to the sum of values of all its parent nodes.
You could try with a smaller query on https://play.dgraph.io
and try to correlate the graph response with the JSON.
{
movie_fraction(func:eq(name@en, "Peter Jackson")){
uid
paths as math(1)
total_films : num_films as count(director.film)
name@en
director.film (first: 5) {
starring(first: 5) {
performance.actor {
path: math(paths)
xx: math(num_films/paths)
fraction : math(paths / (num_films/paths))
name@en
}
}
}
}
}
which produces the following Graph
and has the following JSON response
{
"data": {
"movie_fraction": [
{
"uid": "0x8b77c",
"val(paths)": 1,
"total_films": 0,
"name@en": "Peter Jackson"
},
{
"uid": "0x1cdf22",
"val(paths)": 1,
"total_films": 0,
"name@en": "Peter Jackson"
},
{
"uid": "0x764275",
"val(paths)": 1,
"total_films": 19,
"name@en": "Peter Jackson",
"director.film": [
{
"starring": [
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Tim McLachlan"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Thomas Rimmer"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Jeffrey Thomas"
}
]
},
{
"performance.actor": [
{
"path": 2,
"xx": 19,
"fraction": 0.105263,
"name@en": "Cate Blanchett"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "William Kircher"
}
]
}
]
},
{
"starring": [
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Craig Hall"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Lee Hartley"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Lee Donahue"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Julie Holmes"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Jim Knobeloch"
}
]
}
]
},
{
"starring": [
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Anthony Ray Parker"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Elizabeth Hawthorne"
}
]
},
{
"performance.actor": [
{
"path": 2,
"xx": 19,
"fraction": 0.105263,
"name@en": "Stuart Devenie"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "William Pomeroy"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Angela Bloomfield"
}
]
}
]
},
{
"starring": [
{
"performance.actor": [
{
"path": 2,
"xx": 19,
"fraction": 0.105263,
"name@en": "Stuart Devenie"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Mark Hadlow"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Donna Akersten"
}
]
}
]
},
{
"starring": [
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Hugo Weaving"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "James Nesbitt"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Christopher Lee"
}
]
},
{
"performance.actor": [
{
"path": 1,
"xx": 19,
"fraction": 0.052632,
"name@en": "Ken Stott"
}
]
},
{
"performance.actor": [
{
"path": 2,
"xx": 19,
"fraction": 0.105263,
"name@en": "Cate Blanchett"
}
]
}
]
}
]
},
{
"uid": "0x7dc6b0",
"val(paths)": 1,
"total_films": 0,
"name@en": "Peter Jackson"
}
]
}
}
As you can see from the JSON response, only Cate Blanchett
and Stuart Devenie
have value of path
as 2 which is also observable from the graph since they have two incoming edges. Remember, the value of a variable at a node is the sum of values of the variable for its parent nodes.
Now to answer your questions.
This is because both num_films
and paths
are defined at the same level, so the ratio of their values would remain the same at every level.
I think you meant same as total_films
. A variable has different value at different depths i.e. what we call variable propagation. So the value at a level would depend on the sum of the value of a variable at the parent nodes.
We convert an integer variable to float
before passing it to the division(/) operator and as value of paths
is less than value of num_films/paths
you end up with a fraction. I’d definitely recommend reading the section on Variable propogation in the blogpost.