Test for existence of facet on edge

Hello,
this question is about the same as this (now locked).
In short, how to test for the existence of a facet for on an edge. The use cases are two, one is about data model evolution: we want to implement a feature that will leverage Dgraph’s facets, so at a certain moment in time edges will start to have a facet, and our system will query that values.
But for the update to work we will have to update all the edges at once or run multiple queries just to be sure that we picked up everything, while having a OR not has(property) will simplify the introduction of the new functionality (and give us some peace of mind that we are not missing anything).
The second scenario is the following: let’s say I want to track the marriage status between two people, according to the documentation I can have something like:

{
   <0x1> <spouse> <0x5> 
   <0x1> <spouse> <0x4> (until=2019-01-01)
   <0x1> <spouse> <0x3> (until=2018-01-01)
}

now if I want to get the current spouse of 0x1, the only way I can think of is to retrieve
all the spouse edges (with facets) and check which one doesn’t have a matching until facet set.
That is not ideal imho, especially for cases where the number of edges could be significant: the application will have to retrieve all the edges just to find out the one it needs.

Also please consider this

Do you have a suggestion about how to deal with the use cases described above?

Thanks!

Hi Andrea!

For the second case, you can use sorting on facets and then extract the first result using pagination. The query would look something like this.

{
  	currentSpouse(func: eq(name, "A")){
      name
      spouse @facets(orderdesc: until) (first:1) {
        name
      }
    }
}

For more info about sorting on facets and paginations, please have a look at sorting using facets and pagination.

thanks @Naman,
this would work only if I have one (and one only) edge without the facet property; if there are more than one, I’ll have to fetch the whole results, correct?

1 Like

Oops… I took that marriage example specifically (in which generally there is only one spouse).

You can have a look at assigning facet values to value . What you do is collect all the IDs with predicate spouse, then all predicate spouse with facet value and then filter it out. It would look like:

{
    var(func: eq(name, "A")){
    	allSpouse as spouse
  	}
  	var(func: eq(name, "A")){
      spouse @facets(pastSpouse as until)
    }
  
    currentSpouse(func: uid(allSpouse)) @filter(NOT uid(pastSpouse)){
      name
    }
}

Hope this will work for both the scenarios.

2 Likes

Hey @noandrea,

A trick for your use-case would be to do a regex matching for the date in the facets and return the nodes which doesn’t match. Or a simpler trick would be to use the gt() functionality on a zero date :slight_smile: . For example:

{
  q(func: has(spouse)) {
    uid
    spouse @facets(NOT gt(until, "0000-01-01T00:00:00Z")) {
      uid
    }
  }
}

The above query would return the only spouses with until < year 0000, which is equivalent to not having an until associated with the spouse. I am trying to think of other possible solutions but I guess this would help.

5 Likes

wow @ahsan that’s some acrobatic semantics you pull off right there!

thanks @Naman and @ahsan for the proposed approaches, for the dateTime use case
my preferred solution is @facets(NOT gt(until, "0000-01-01T00:00:00Z")) since it is shorter and easy to chain with other predicates.

But probably for other data types the @Naman approach would be useful.

Any chances that Improve Facets functions. (not supported in preprocessFilter) · Issue #2896 · dgraph-io/dgraph · GitHub will be picked up during the adjustments of the facets reply format ?

3 Likes

This should be in the Dgraph category not Graphql. @ahsan can you edit the category?

3 Likes

True, fixed, thanks!