I need to get distinct nodes by a given criteria. For example, I have tree customer nodes linked to one node(In the next example: 3 nodes share “Somehting In Common” node). Any of the customer nodes is linked to name node. But some customer nodes can share same name.
Given the following graph
{
set {
_:l “Something In Common” .
How can I count, what is the number of distinct names related to “Something In Common” node?
I have tried with something like
{
me(func: eq(commondInfo, “Something In Common”) ) {
commondInfo
~linked_to @groupby(name) {
has_name_count as count(name)
}
sum(val(has_name_count))
}
}
but it does not work. Is there a way to make a distinct operation? I have checked in the documentation and forum, but I cannot find an example.
{
set {
_:l <Common_name> "Something In Common" .
_:lK <more_details> "More details about Something In Common" .
_:T <Common_name> "Something In Common2" .
_:TK <more_details> "More details about Something In Common" .
_:a <name> "1123" .
_:b <name> "1124" .
_:c <name> "1125".
_:l <linked_to> _:a (timestamp="2018-05-23") .
_:l <linked_to> _:b (timestamp="2018-05-23") .
_:T <linked_to> _:c (timestamp="2018-05-23") .
_:aName <name> "A A" . #I don't know if its needed
_:cName <name> "C C" . #I don't know if its needed
_:anotherName <name> "Another Not Taken into Account " . #I don't know if its needed
_:a <has_name> _:aName (timestamp="2018-05-21") .
_:b <has_name> _:aName (timestamp="2018-05-22") .
_:c <has_name> _:cName (timestamp="2018-05-23") .
}
}
Queries you can use:
{
#Find all and expand all
usersIncommon(func: has(Common_name)){
expand(_all_){expand(_all_)}
}
}
{
#Filter by Common_name and expand all
usersIncommon(func: has(Common_name)) @filter(eq(Common_name, "Something In Common")){
uid
Common_name
linked_to {
name
}
}
}
{
#Using two blocks to filter and return a clean result
var(func: has(Common_name)) @filter(eq(Common_name, "Something In Common")){
uid
Common_name
myvar AS linked_to{
name
}
}
usersIncommon(func: uid(myvar)) {
uid
has_name
name
}
}
{
#count linked by linked_to
usersIncommon(func: has(Common_name)) {
uid
Common_name
linked_to {
name
}
count(linked_to)
}
}
Thank you very much for your answer. Expand is a pretty cool function! But I need a little more help to get the count I need. I will change a little bit the mutation script.
{
set {
#common ip
_:l <ip> "123.123.123.123" .
_:l <ip_counry_range> "Some ip country range".
_:T <ip> "123.123.123.124" .
_:T <ip_country_range> "Some other ip country range.NOTE: We don't care of this ip in the search result, we just have in the database" .
#customers
_:a <customerId> "1123" .
_:b <customerId> "1124" .
_:c <customerId> "1125".
#customer has used the common ip on the following dates
_:l <linked_to> _:a (timestamp="2018-05-23") .
_:l <linked_to> _:b (timestamp="2018-05-23") .
_:T <linked_to> _:c (timestamp="2018-05-23") .
#customer name nodes, more than one customer can share one name
_:aName <name> "A A" .
_:cName <name> "C C" .
_:anotherName <name> "Another Not Taken into Account " . #I don't know if its needed
#custoemrs used that names on a given date
_:a <has_name> _:aName (timestamp="2018-05-21") .
_:b <has_name> _:aName (timestamp="2018-05-22") .
_:c <has_name> _:cName (timestamp="2018-05-23") .
}
}
I need to get the count of the names, starting from something in common node. For example you have an customer base, full of customers that can have common names and ips that customers have used in the past. So ip can be something in common. And I want to take what is the count of the unique names for a given ip.
In the given graph above, for ip 123.123.123.123 we have two customers with same name(a and b). If I count the linked_to edge the names count will be two, which is not true since it is actually one.
{
#count linked by linked_to
usersIncommon(func: has(ip)) @filter(eq(ip, "123.123.123.123")){
uid
ip
linked_to {
name
}
count(linked_to)
}
}
So how can I count the name nodes not linked_to edges?
Similar to sql llike syntax: select distinct data from some table;
Count only works on links via UID, so you should always think of “nodes levels”.
In case you would have to change has_name to UID and if you need “@Reverse” (if it is not already).
In this case your query would be - Try this out:
{
usersIncommon(func: has(ip)) @filter(eq(ip, "123.123.123.123")){
uid
ip
linked_to {
name
has_name { #if your nodes are reverse use like this "~has_name"
name
}
count(has_name)
}
count(linked_to)
}
}
Maybe I did not quite understand what you want. I would recommend giving a hand in the documentation on the language. https://docs.dgraph.io/query-language/ There are many possibilities, so I understand you might have to create more than one block with variables to filter out each need and generate the count. In that case you need to mix your business-logic(app logic) knowledge with the Dgraph language.
I believe that by mastering language you can do a lot. However, not everything should be done by DB alone. Dgraph has many functions, but you can not do everything.