Summing over facets

Hi, I have been running into this issue where I can’t seem to correctly query for the sum of the facets for multiple nodes.

For a minimal example: https://docs.dgraph.io/query-language/#facets-and-aggregation Here, instead of querying the average rating for each movie, if we wanted to simply output the sum of the ratings of each movie… I tried to run the following query:

{
  var(func: has(rated)) {
    rated @facets(r as rating)
    total_rating as sum(r)
   }

  data(func: uid(total_rating)) {
    name
    val(total_rating)
  }
}

and I get weird results like:

{
  "data": {
    "data": [
      {
        "name": "Movie 1",
        "val(total_rating)": 33
      },
      {
        "name": "Movie 2",
        "val(total_rating)": 33
      },
      {
        "name": "Movie 3",
        "val(total_rating)": 33
      }
    ]
  }
}

when the sums should be 8, 7 and 10 respectively…

Any pointers on what I am doing wrong? I am guessing this has something to do with value propagation but I don’t understand what I can do to fix it.

Hi there,

This is really interesting and totally a bug!

I filed issue #4160 where you can see the whole reasoning behind the current values you’re obtaining and why they’re wrong.

I’d like to propose a workaround, but at this point, I think the best option is to simply do the sum on the client side.

Thanks for reporting this!

1 Like

That one is tricky. Cuz the sum func is applied to nodes(entities), not values that are between two entities. So the sum would be applied correctly (and it would assume that values ​​in facets belong to one level, after all the query has only one level) to the first-class citizens only, when you’re doing a wide query. That’s why we have the sum of all ratings together. Cuz facets can’t simulate “first-class”.

One way to “solve” this, is to use pagination. And paginate one by one. So you can have the values you need. That’s a “hacky” way of doing it. But if you still wanna do it in the DB query that’s the way.

e.g:

{
  var(func: has(~rated) , first:1, offset:0) { # offset: 0|1|2...
    ~rated @facets(r as rating)
      total_rating as sum(val(r))
      }
  data(func: uid(total_rating)) {
    name
    val(total_rating)
  }
}

As I imagine, to support this we would create a kind of “temporary emancipation of facets as first-class” (funny phrase hehe) just to apply this. I think that this could take time to be implemented. So do it on the client-side as Francesc says or in a “hacky” way.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.