Unable to alias and sort on facet value


(Thej Kamal Rao Menneni) #1

I am trying to use query variables to find common profiles and then finding top matching profile on top of it using sort. Unfortunately I cannot alias facet value and unable to find top scoring record.

following is my data

_:PERSON1 <person_name> “PERSON1” . #
_:PERSON2 <person_name> “PERSON2” . #
_:PERSON3 <person_name> “PERSON3” . #
_:profile1 <profile_id> “z1” . #
_:profile2 <profile_id> “z2” . #
_:profile3 <profile_id> “z3” . #
_:profile4 <profile_id> “z4” . #
_:profile5 <profile_id> “z5” . #
_:profile6 <profile_id> “z6” . #
_:profile7 <profile_id> “z7” . #
_:profile8 <profile_id> “z8” . #
_:profile1 <post_value> _:profile8 (score=60,field=“post_value”,match=“B”,value=“AAB”) . #
_:profile1 <post_value> _:profile7 (score=70,field=“post_value”,match=“A”,value=“AAB”) . #
_:profile2 <post_value> _:profile7 (score=65,field=“post_value”,match=“BA”,value=“AAB”) . #
_:profile2 <post_value> _:profile5 (score=85,field=“post_value”,match=“AB”,value=“AAB”) . #
_:profile4 <post_value> _:profile5 (score=80,field=“post_value”,match=“AB”,value=“AABB”) . #
_:profile6 <post_value> _:profile5 (score=90,field=“post_value”,match=“AB”,value=“BAA”) . #
_:profile8 <post_value> _:profile1 (score=60,field=“post_value”,match=“AAB”,value=“B”) . #
_:profile7 <post_value> _:profile1 (score=70,field=“post_value”,match=“AAB”,value=“A”) . #
_:profile7 <post_value> _:profile2 (score=65,field=“post_value”,match=“AAB”,value=“BA”) . #
_:profile5 <post_value> _:profile2 (score=85,field=“post_value”,match=“AAB”,value=“AB”) . #
_:profile5 <post_value> _:profile4 (score=80,field=“post_value”,match=“AABB”,value=“AB”) . #
_:profile5 <post_value> _:profile6 (score=90,field=“post_value”,match=“BAA”,value=“AB”) . #
_:profile1 <belongs_to> _:PERSON1 . #
_:profile2 <belongs_to> _:PERSON1 . #
_:profile3 <belongs_to> _:PERSON1 . #
_:profile4 <belongs_to> _:PERSON1 . #
_:profile6 <belongs_to> _:PERSON2 . #
_:profile7 <belongs_to> _:PERSON2 . #
_:profile8 <belongs_to> _:PERSON2 . #
_:profile5 <belongs_to> _:PERSON3 . #

profile belongs to person and it’s a reverse edge. Given 2 person names, I need to identify top scoring post_value edge. In this case if we select person1 and person2, top scoring edge will be
_:profile2 <post_value> _:profile5 (score=85,field=“post_value”,match=“AB”,value=“AAB”) . #

I would like to use sort feature so that I get access to full record.

Following is my query to get all common post values between Person1 and Person2

{
    var(func: eq(person_name, "PERSON1")) {
     ~belongs_to{
        profile_id
        post_value{
            A as profile_id # A
            }
        }
    }
  
    var(func: eq(person_name, "PERSON_2")) { 
    ~belongs_to{
            B as profile_id{ # B
          
            }
        }
    }
  
    level3(func: uid(A)) @filter(uid(B))@cascade @normalize{ # profiles from both A & B
        source_profile_id: profile_id
        belongs_to@filter(eq(person_name, "PERSON2")){
          source_person_name: person_name
        }
        post_value @facets(field, match, score, value, orderdesc: score){
            belongs_to@filter(eq(person_name, "PERSON1")){
            target_person_name: person_name
          }
        }
    }
}

But I am interested in identifying only highest scored post_value between Person1 and Person2.

Please note that profile1 might have multiple post_value edges hence I need to first find common profiles between selected persons and then find highest post value for each profile and then finally finding top scoring among all profiles.

Please help. Thank you.


(Thej Kamal Rao Menneni) #2

Any recommendation to find common post values in the above data model? or changing data model itself will help?


(Michel Conrado (Support Engineer)) #3

Hi, Menneni.

Particularly I was a bit confused by its structure of yours. So I decided to create a model according to what I understood of your need.

Other details: The title seems confusing with the content of the post. The title seems to claim that there are problems with alias, sort and facet. Which is not quite true. At first you just want to get the highest value taken from a Facet.

Tip: When to send us a mudation or JSON. Please do via some gist (like GitHub Gist). Discuss has a habit of modifying some characters as quotation marks for example. This hinders a quick response. Because I have to edit all RDF as it was in your case.

Here’s an example. Analyze and let’s talk.

The mutation

A Query

{
  #   show-me_some_users_please(func: has(~user)){
  #     uid
  #     name
  #     age
  #     Posts {title}
  #     rated {expand(_all_)}
  # }
  
  var(func: has(rated), first:1001) { #If you have more than a thousand nodes (Nodes rated) you need to "first:1001" because there is a limitation by default.
		uid
    num_raters as math(3)
    rated @facets(r as rating) {
      total_rating as math(r)
      average_rating as math(total_rating / num_raters)
    }
  }
  data(func: uid(total_rating), orderdesc: val(total_rating)) {
    title
    val(total_rating)
    val(average_rating)
  }
  winner_of_the_night() {
    max(val(total_rating))
  }

}

The Result

{
  "data": {
    "data": [
      {
        "title": "Michael second post",
        "val(total_rating)": 240,
        "val(average_rating)": 40
      },
      {
        "title": "Michael first post",
        "val(total_rating)": 210,
        "val(average_rating)": 35
      },
      {
        "title": "Amit first post",
        "val(total_rating)": 80,
        "val(average_rating)": 26.666667
      },
      {
        "title": "Amit second post",
        "val(total_rating)": 50,
        "val(average_rating)": 16.666667
      }
    ],
    "winner_of_the_night": [
      {
        "max(val(total_rating))": 240
      }
    ]
  }

Query for the “winner”

Change the query asking just for 1 result, using “first:1”. It’s a trick, but is the wanted result.

winner(func: uid(total_rating), orderdesc: val(total_rating), first:1) {
    title
    val(total_rating)
    val(average_rating)
  }

{
  "data": {
    "winner": [
      {
        "title": "Michael second post",
        "val(total_rating)": 240,
        "val(average_rating)": 40
      }
    ]
  }

(Thej Kamal Rao Menneni) #4

Thank you for the response @MichelDiz. I am sorry if my example data is confusing. I have created gist in github here, please check.

https://gist.github.com/menneni/66e9ad2cd59e29289771c3366cc8dc93

Your example data and queries helped to understand aliasing facet value and use it later in another function but it didn’t solve my problem completely.

total_rating as math(r) in your query, does summation of all ratings on each post, which helps in identifying post which has highest cumulative rating. In this example, michaelfirst node ratings cumulative rating is higher i.e 240. But I want to find out highest rated record among all ratings, in your example sarah’s rating for ‘michael first post’ is highest i.e 180 compared to other ratings [150, 80, 50, 30].

Hope you understood my problem. Let me know whether it’s possible through Dgraph. Thank you.


(Michel Conrado (Support Engineer)) #5

Actually is michaelsecond (post) who has the highest rating.

Can you check if it fits for you?

{

  var(func: has(~rated), first:1) {
    title
   user as ~rated @facets(r as rating)( first:1)
  }
    data(func: uid(user), orderdesc: val(r), first:10000) {
    name@.
    age
    highest_given : val(r)
  }
}

Also this (extra)

{
  var(func: has(~rated), first:1000) {
   user as ~rated @facets(r as rating)(first:1000)
  }
    data(func: uid(user), orderdesc: val(r), first:1000) {
    name@.
    age
    highest_given : val(r)
  }
}

{
  "description": "Find the highest guy who is maniac for rates"
}

Cheers.


(Thej Kamal Rao Menneni) #6

It didn’t help @MichelDiz. It still does summation of all ratings and returns post having highest cumulative value i.e. michaelsecond post. As I discussed earlier, I need highest rating record in above case michaelfirst which received 180.

Following is the problem I am trying to solve

  1. Person (node) has (relationship) multiple profiles (nodes)
  2. Profile has address and few other properties
  3. if two profiles have similar address, they will share an edge between them (relationship with similarity score as facet value)

I am trying to build graph which shows link between profiles if they have similar address, with facet value as similarity score.

If we select any two persons, in graph I need to show edge having max similarity score between profiles belonging to selected persons.

In above query when you alias facet, it tries group it and returns summation of all values belonging to that edge. I doubt its a bug instead of giving an array of values, I get summation of values, looks non intuitive.

Hope problem is clear now. Please let me know whether it’s possible through Dgraph. Thank you.


(Thej Kamal Rao Menneni) #7

Thank you for the response @MichelDiz. Unfortunately It didn’t help. I am not really sure why you’re doing func: has(~rated), first:1) which basically picks first edge and ignores others.

It’s non intuitive to get sum of facet values for given node when what I need is array of values and get highest.

Following is the problem I am trying to solve

  1. Person (node) has (relationship) multiple profiles/accounts (nodes)
  2. Account has address and few other properties
  3. if two accounts have similar address, they will share an edge between them (relationship with similarity score as facet value)

I am trying to build graph which shows link between profiles if they have similar address, with facet value as similarity score.

If we select any two persons, in graph I need to show edge having max similarity score between accounts belonging to selected persons.

Notes: I also observed that I won’t get results when I use @cascade and pagination together

{
  var(func: eq(person_name, "person1"))@cascade{
    ~belongs_to_person {
    	source_profile_id: profile_id
    	record as address@facets(r as  score)(first: 1){
      	target_profile_id: profile_id
     		belongs_to_person @filter(eq(person_name, "person2")){
      		target_person_name: person_name
    		}
    	}
  	}
  }
  data(func: uid(record), orderdesc: val(r), first: 1){
    profile_id
    highest: val(r)
  }
}

(Thej Kamal Rao Menneni) #8

Any help on this query?