Facets on relations

Trying to figure out how to work with facets on multiple edges of a predicate.

For example, with a mutation like this -

{
  set {
    <0x01> <seen> <0x02> (tag="example") .
    <0x01> <seen> <0x03> (tag="another") .
	}
}

I write a query like this:

query {
  r(func: uid(0x01)) {
    seen @facets {
      uid
    }
  }
}

And facets appear in a very strange way in the returned data, like so:

  "data": {
    "r": [
      {
        "seen": [
          { "uid": "0x2" },
          { "uid": "0x3" }
        ],
        "seen|tag": {
          "0": "example",
          "1": "another"
        }
      }
    ]
  }

I would really expect to see facets appear in the response similar to the way they were sent. But instead these appear in an “unrelated” object. Even Ratel shows them as [object] instead of showing the actual values.

Is there a way to get the response more like so:

  "data": {
    "r": [
      {
        "seen": [
          { "uid": "0x2", "tag": "example" },
          { "uid": "0x3", "tag": "another" }
        ]
      }
    ]
  }

Am I missing something here? Or is this so weird by design?

This is a new design for facets in latest releases.

I had to write a convoluted processing function to get facets into a format that is usable :frowning:

The original query is something like this:

query {
  results(func: eq(dgraph.type, "Node"))
    @recurse(loop: false)
    @filter(has(Links))
  {
    Name
    Links @facets
  }
}

And the function to turn it into a usable data structure -

function destructureFacets(res, queryName = 'results', listName = 'Links') {
  return res.data[queryName].map(
    (result) => {
      const facets = Object.keys(result).map(
        facet => facet.startsWith(listName + '|') ? facet : undefined
      ).filter(x => x)
      for (let idx of result[listName].keys()) {
        for (let facet of facets) {
          if (typeof result[facet][idx] !== 'undefined') {
            result[listName][idx][facet.slice(listName.length + 1)] = result[facet][idx]
          }
          delete result[facet][idx]
          for (let foreignFacet of Object.keys(result[listName][idx])) {
            if (foreignFacet.startsWith(listName + '|')) {
              delete result[listName][idx][foreignFacet]
            }
          }
        }
      }
      // remove "used" facets from main result object
      for (let facet of facets) {
        delete result[facet]
      }
      return result
    }
  )
}
1 Like

@kesor this is working as expected. Earlier facets for uid edges were returning as part of the object but then the same was not possible for scalar edges, say an edge of type [string].

Now we have a common format for both where the facets are returned as part of another object where the index of the object represents the index in the original array (seen here) that the facet belongs to. I am not sure about your javascript code but fetching the value of a facet should be as simple as seeking to the index of the current array item in the facets object.

1 Like