Flattening + aggregation of nested relationships

Hello. I have the following schema

  title: string @index(term) .
  term: string @index(term) .
  category: string @index(term) .
  has_category: uid @reverse .
  has_term: [uid] @reverse .

  type Category {
    category
  }

  type Term {
    term
  }

  type Article {
    title
    has_category
    has_term
  }

With the following relationships:

  • Article → (has_category) → Category
  • Article → (has_term with has_term|appears facet) → Term

What I am trying to achieve is map back from a list of terms to their categories. Once I have that, I want to groupby term + category to calculate total sum of appears facet.

The closest I got is:

query main($text: string){
	q(func: anyofterms(term, $text), first: 2) @filter(eq(dgraph.type, "Term")) {
    term: term
  	~has_term @normalize {
      title
      has_category {
        category:category
      }
      appears:  val(a)
    } @facets (a as appears)
  }
}

Which returns:

 [
      {
        "term": "anyon",
        "~has_term": [
          {
            "appears": 1,
            "category": "Health"
          },
          {
            "appears": 3,
            "category": "Health"
          },
      ]
}
]

I can’t seem to find a way to make those entries of Health be summed together

Sorry, but what is the relation with GraphQL?

This facet directive is in the wrong place. It should be:

~has_term @normalize @facets (a as appears) { ...

Oh, my apollogies, i think I chose an incorrect tag. I’ve moved the facets, but I am still not sure how to solve the problem?

Edit: I’ve chosen a different tag for the question.

Please, share a small sample of your data. Cuz I can’t get where the facets would come from. Just to be sure.

Yes of course.

{
  set {
    _:category <dgraph.type> "Category" .
    _:category <category> "Health" .

    _:term <dgraph.type> "Term" .
    _:term <term> "health" .

    _:article <dgraph.type> "Article" .
    _:article <title> "health is good" .
    _:article <has_category> _:category .
    _:article <has_term> _:term (appears=3) .

    _:article2 <dgraph.type> "Article" .
    _:article2 <title> "health is bad" .
    _:article2 <has_category> _:category .
    _:article2 <has_term> _:term (appears=2) .
  }
}

The variables text: "health". The expected output I’d like is:

[
      {
        "term": "health",
        "~has_term": [
          {
            "appears": 5,
            "category": "Health"
          }
        ],
      }
    ]

Essentially doing something like groupby (term, category) to get the sum of appears

Do you mean something like this?

query main($text: string = "health"){
	q(func: anyofterms(term, $text), first: 2) @filter(eq(dgraph.type, "Term")) {
    term: term
  	~has_term @normalize @facets (a as appears) {
      title
      has_category {
        category : category
      }
    } 
      appears : sum(val(a))
  }
}
{
  "data": {
    "q": [
      {
        "term": "health",
        "~has_term": [
          {
            "category": "Health",
            "~has_term|appears": 3
          },
          {
            "category": "Health",
            "~has_term|appears": 2
          }
        ],
        "appears": 5
      }
    ]
  }
}

Not quite. I can’t sum the appears value as I want it to be grouped by category (a term can belong to multiple categories). I want the has_term array to combine entries that have the same category and combine the has_terms|appears value. With the current state we have something like this:

term | category | appears
health | Health | 3
health | Health | 2
health | Insurance | 1

I’d like:

term | category | appears
health | Health | 5
health | Insurance | 1

If this is not possible I’ll just have to do this in code.

I don’t think it is possible, unless I got it wrong.

Putting normalize on the root query you can “flat” it and repeat the value on both objects. This would be the most similar to what I got.

query main($text: string = "health"){
	q(func: anyofterms(term, $text), first: 2) @filter(eq(dgraph.type, "Term")) @normalize {
    term: term
  	~has_term  @facets (a as appears) {
      title
      has_category {
        category : category
      }
    } 
      appears : sum(val(a))
  }
}
{
  "data": {
    "q": [
      {
        "appears": 5,
        "category": "Health",
        "term": "health",
        "~has_term|appears": 3
      },
      {
        "appears": 5,
        "category": "Health",
        "term": "health",
        "~has_term|appears": 2
      }
    ]
  }
}